[Scummvm-cvs-logs] SF.net SVN: scummvm: [20703] scummvm/trunk/engines/scumm
sev at users.sourceforge.net
sev at users.sourceforge.net
Wed Feb 15 10:51:02 CET 2006
Revision: 20703
Author: sev
Date: 2006-02-15 10:48:49 -0800 (Wed, 15 Feb 2006)
ViewCVS: http://svn.sourceforge.net/scummvm?rev=20703&view=rev
Log Message:
-----------
o Renamed script_v6he.cpp and script_v7he.cpp to script_v60he.cpp and
script_v70he.cpp respectively since we use 2 digits for HE versioning.
o Also renamed resource_v7he.* to resource_he.* because it is actually not
HE70-specific but is used by all HE70+ titles.
Modified Paths:
--------------
scummvm/trunk/engines/scumm/cursor.cpp
scummvm/trunk/engines/scumm/he/script_v100he.cpp
scummvm/trunk/engines/scumm/he/script_v72he.cpp
scummvm/trunk/engines/scumm/he/script_v80he.cpp
scummvm/trunk/engines/scumm/he/script_v90he.cpp
scummvm/trunk/engines/scumm/module.mk
scummvm/trunk/engines/scumm/scumm.cpp
Added Paths:
-----------
scummvm/trunk/engines/scumm/he/resource_he.cpp
scummvm/trunk/engines/scumm/he/resource_he.h
scummvm/trunk/engines/scumm/he/script_v60he.cpp
scummvm/trunk/engines/scumm/he/script_v70he.cpp
Removed Paths:
-------------
scummvm/trunk/engines/scumm/he/resource_v7he.cpp
scummvm/trunk/engines/scumm/he/resource_v7he.h
scummvm/trunk/engines/scumm/he/script_v6he.cpp
scummvm/trunk/engines/scumm/he/script_v7he.cpp
Modified: scummvm/trunk/engines/scumm/cursor.cpp
===================================================================
--- scummvm/trunk/engines/scumm/cursor.cpp 2006-02-15 18:48:56 UTC (rev 20702)
+++ scummvm/trunk/engines/scumm/cursor.cpp 2006-02-15 18:48:49 UTC (rev 20703)
@@ -28,7 +28,7 @@
#include "scumm/intern.h"
#include "scumm/he/intern_he.h"
#include "scumm/object.h"
-#include "scumm/he/resource_v7he.h"
+#include "scumm/he/resource_he.h"
#include "scumm/saveload.h"
#include "scumm/scumm.h"
Copied: scummvm/trunk/engines/scumm/he/resource_he.cpp (from rev 20696, scummvm/trunk/engines/scumm/he/resource_v7he.cpp)
===================================================================
--- scummvm/trunk/engines/scumm/he/resource_he.cpp (rev 0)
+++ scummvm/trunk/engines/scumm/he/resource_he.cpp 2006-02-15 18:48:49 UTC (rev 20703)
@@ -0,0 +1,1912 @@
+/* ScummVM - Scumm Interpreter
+ * Copyright (C) 2004-2006 The ScummVM project
+ *
+ * Parts of code heavily based on:
+ * icoutils - A set of programs dealing with MS Windows icons and cursors.
+ * Copyright (C) 1998-2001 Oskar Liljeblad
+ *
+ * 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/stdafx.h"
+#include "scumm/scumm.h"
+#include "scumm/he/intern_he.h"
+#include "scumm/resource.h"
+#include "scumm/he/resource_he.h"
+#include "scumm/sound.h"
+#include "scumm/util.h"
+#include "sound/wave.h"
+
+#include "common/stream.h"
+#include "common/system.h"
+
+namespace Scumm {
+
+ResExtractor::ResExtractor(ScummEngine_v70he *scumm)
+ : _vm(scumm) {
+
+ _fileName[0] = 0;
+ memset(_cursorCache, 0, sizeof(_cursorCache));
+}
+
+ResExtractor::~ResExtractor() {
+ for (int i = 0; i < MAX_CACHED_CURSORS; ++i) {
+ CachedCursor *cc = &_cursorCache[i];
+ if (cc->valid) {
+ free(cc->bitmap);
+ free(cc->palette);
+ }
+ }
+ memset(_cursorCache, 0, sizeof(_cursorCache));
+}
+
+ResExtractor::CachedCursor *ResExtractor::findCachedCursor(int id) {
+ for (int i = 0; i < MAX_CACHED_CURSORS; ++i) {
+ CachedCursor *cc = &_cursorCache[i];
+ if (cc->valid && cc->id == id) {
+ return cc;
+ }
+ }
+ return NULL;
+}
+
+ResExtractor::CachedCursor *ResExtractor::getCachedCursorSlot() {
+ uint32 min_last_used = 0;
+ CachedCursor *r = NULL;
+ for (int i = 0; i < MAX_CACHED_CURSORS; ++i) {
+ CachedCursor *cc = &_cursorCache[i];
+ if (!cc->valid) {
+ return cc;
+ } else {
+ if (min_last_used == 0 || cc->last_used < min_last_used) {
+ min_last_used = cc->last_used;
+ r = cc;
+ }
+ }
+ }
+ assert(r);
+ free(r->bitmap);
+ free(r->palette);
+ memset(r, 0, sizeof(CachedCursor));
+ return r;
+}
+
+void ResExtractor::setCursor(int id) {
+ byte *cursorRes = 0;
+ int cursorsize;
+ int keycolor = 0;
+ CachedCursor *cc = findCachedCursor(id);
+ if (cc != NULL) {
+ debug(7, "Found cursor %d in cache slot %d", id, cc - _cursorCache);
+ } else {
+ cc = getCachedCursorSlot();
+ assert(cc && !cc->valid);
+ cursorsize = extractResource(id, &cursorRes);
+ convertIcons(cursorRes, cursorsize, &cc->bitmap, &cc->w, &cc->h, &cc->hotspot_x, &cc->hotspot_y, &keycolor, &cc->palette, &cc->palSize);
+ debug(7, "Adding cursor %d to cache slot %d", id, cc - _cursorCache);
+ free(cursorRes);
+ cc->valid = true;
+ cc->id = id;
+ cc->last_used = g_system->getMillis();
+ }
+
+ if (_vm->_system->hasFeature(OSystem::kFeatureCursorHasPalette) && cc->palette)
+ _vm->_system->setCursorPalette(cc->palette, 0, cc->palSize);
+
+ _vm->setCursorHotspot(cc->hotspot_x, cc->hotspot_y);
+ _vm->setCursorFromBuffer(cc->bitmap, cc->w, cc->h, cc->w);
+}
+
+
+/*
+ * Static variables
+ */
+const char *res_types[] = {
+ /* 0x01: */
+ "cursor", "bitmap", "icon", "menu", "dialog", "string",
+ "fontdir", "font", "accelerator", "rcdata", "messagelist",
+ "group_cursor", NULL, "group_icon", NULL,
+ /* the following are not defined in winbase.h, but found in wrc. */
+ /* 0x10: */
+ "version", "dlginclude", NULL, "plugplay", "vxd",
+ "anicursor", "aniicon"
+};
+#define RES_TYPE_COUNT (sizeof(res_types)/sizeof(char *))
+
+Win32ResExtractor::Win32ResExtractor(ScummEngine_v70he *scumm) : ResExtractor(scumm) {
+}
+
+int Win32ResExtractor::extractResource(int resId, byte **data) {
+ char buf[20];
+
+ snprintf(buf, sizeof(buf), "%d", resId);
+
+ return extractResource_("group_cursor", buf, data);
+}
+
+int Win32ResExtractor::extractResource_(const char *resType, char *resName, byte **data) {
+ char *arg_language = NULL;
+ const char *arg_type = resType;
+ char *arg_name = resName;
+ int arg_action = ACTION_LIST;
+ int ressize = 0;
+
+ _arg_raw = false;
+
+ /* translate --type option from resource type string to integer */
+ arg_type = res_type_string_to_id(arg_type);
+
+ WinLibrary fi;
+
+ /* initiate stuff */
+ fi.memory = NULL;
+ fi.file = new Common::File;
+
+ if (!_fileName[0]) { // We are running for the first time
+ snprintf(_fileName, 256, "%s.he3", _vm->getBaseName());
+
+ if (_vm->_substResFileNameIndex > 0) {
+ char buf1[128];
+
+ _vm->generateSubstResFileName(_fileName, buf1, sizeof(buf1));
+ strcpy(_fileName, buf1);
+ }
+ }
+
+
+ /* get file size */
+ fi.file->open(_fileName);
+ if (!fi.file->isOpen()) {
+ error("Cannot open file %s", _fileName);
+ }
+
+ fi.total_size = fi.file->size();
+ if (fi.total_size == -1) {
+ error("Cannot get size of file %s", fi.file->name());
+ goto cleanup;
+ }
+ if (fi.total_size == 0) {
+ error("%s: file has a size of 0", fi.file->name());
+ goto cleanup;
+ }
+
+ /* read all of file */
+ fi.memory = (byte *)malloc(fi.total_size);
+ if (fi.file->read(fi.memory, fi.total_size) == 0) {
+ error("Cannot read from file %s", fi.file->name());
+ goto cleanup;
+ }
+
+ /* identify file and find resource table */
+ if (!read_library(&fi)) {
+ /* error reported by read_library */
+ goto cleanup;
+ }
+
+ // verbose_printf("file is a %s\n",
+ // fi.is_PE_binary ? "Windows NT `PE' binary" : "Windows 3.1 `NE' binary");
+
+ /* errors will be printed by the callback */
+ ressize = do_resources(&fi, arg_type, arg_name, arg_language, arg_action, data);
+
+ /* free stuff and close file */
+ cleanup:
+ if (fi.file != NULL)
+ fi.file->close();
+ if (fi.memory != NULL)
+ free(fi.memory);
+
+ return ressize;
+}
+
+
+/* res_type_id_to_string:
+ * Translate a numeric resource type to it's corresponding string type.
+ * (For informative-ness.)
+ */
+const char *Win32ResExtractor::res_type_id_to_string(int id) {
+ if (id == 241)
+ return "toolbar";
+ if (id > 0 && id <= (int)RES_TYPE_COUNT)
+ return res_types[id-1];
+ return NULL;
+}
+
+/* res_type_string_to_id:
+ * Translate a resource type string to integer.
+ * (Used to convert the --type option.)
+ */
+const char *Win32ResExtractor::res_type_string_to_id(const char *type) {
+ static const char *res_type_ids[] = {
+ "-1", "-2", "-3", "-4", "-5", "-6", "-7", "-8", "-9", "-10",
+ "-11", "-12", NULL, "-14", NULL, "-16", "-17", NULL, "-19",
+ "-20", "-21", "-22"
+ };
+ int c;
+
+ if (type == NULL)
+ return NULL;
+
+ for (c = 0 ; c < (int)RES_TYPE_COUNT ; c++) {
+ if (res_types[c] != NULL && !scumm_stricmp(type, res_types[c]))
+ return res_type_ids[c];
+ }
+
+ return type;
+}
+
+int Win32ResExtractor::extract_resources(WinLibrary *fi, WinResource *wr,
+ WinResource *type_wr, WinResource *name_wr,
+ WinResource *lang_wr, byte **data) {
+ int size;
+ bool free_it;
+ const char *type;
+ int32 id;
+
+ if (*data) {
+ error("Win32ResExtractor::extract_resources() more than one cursor");
+ return 0;
+ }
+
+ *data = extract_resource(fi, wr, &size, &free_it, type_wr->id, (lang_wr == NULL ? NULL : lang_wr->id), _arg_raw);
+
+ if (data == NULL) {
+ error("Win32ResExtractor::extract_resources() problem with resource extraction");
+ return 0;
+ }
+
+ /* get named resource type if possible */
+ type = NULL;
+ if ((id = strtol(type_wr->id, 0, 10)) != 0)
+ type = res_type_id_to_string(id);
+
+ debugC(DEBUG_RESOURCE, "extractCursor(). Found cursor name: %s%s%s [size=%d]",
+ get_resource_id_quoted(name_wr),
+ (lang_wr->id[0] != '\0' ? " language: " : ""),
+ get_resource_id_quoted(lang_wr), size);
+
+ return size;
+}
+
+/* extract_resource:
+ * Extract a resource, returning pointer to data.
+ */
+byte *Win32ResExtractor::extract_resource(WinLibrary *fi, WinResource *wr, int *size,
+ bool *free_it, char *type, char *lang, bool raw) {
+ char *str;
+ int32 intval;
+
+ /* just return pointer to data if raw */
+ if (raw) {
+ *free_it = false;
+ /* get_resource_entry will print possible error */
+ return get_resource_entry(fi, wr, size);
+ }
+
+ /* find out how to extract */
+ str = type;
+ if (str != NULL && (intval = strtol(STRIP_RES_ID_FORMAT(str), 0, 10))) {
+ if (intval == (int)RT_GROUP_ICON) {
+ *free_it = true;
+ return extract_group_icon_cursor_resource(fi, wr, lang, size, true);
+ }
+ if (intval == (int)RT_GROUP_CURSOR) {
+ *free_it = true;
+ return extract_group_icon_cursor_resource(fi, wr, lang, size, false);
+ }
+ }
+
+ return NULL;
+}
+
+/* extract_group_icon_resource:
+ * Create a complete RT_GROUP_ICON resource, that can be written to
+ * an `.ico' file without modifications. Returns an allocated
+ * memory block that should be freed with free() once used.
+ *
+ * `root' is the offset in file that specifies the resource.
+ * `base' is the offset that string pointers are calculated from.
+ * `ressize' should point to an integer variable where the size of
+ * the returned memory block will be placed.
+ * `is_icon' indicates whether resource to be extracted is icon
+ * or cursor group.
+ */
+byte *Win32ResExtractor::extract_group_icon_cursor_resource(WinLibrary *fi, WinResource *wr, char *lang,
+ int *ressize, bool is_icon) {
+ Win32CursorIconDir *icondir;
+ Win32CursorIconFileDir *fileicondir;
+ byte *memory;
+ int c, offset, skipped;
+ int size;
+
+ /* get resource data and size */
+ icondir = (Win32CursorIconDir *)get_resource_entry(fi, wr, &size);
+ if (icondir == NULL) {
+ /* get_resource_entry will print error */
+ return NULL;
+ }
+
+ /* calculate total size of output file */
+ RETURN_IF_BAD_POINTER(NULL, icondir->count);
+ skipped = 0;
+ for (c = 0 ; c < icondir->count ; c++) {
+ int level;
+ int iconsize;
+ char name[14];
+ WinResource *fwr;
+
+ RETURN_IF_BAD_POINTER(NULL, icondir->entries[c]);
+ /*printf("%d. bytes_in_res=%d width=%d height=%d planes=%d bit_count=%d\n", c,
+ icondir->entries[c].bytes_in_res,
+ (is_icon ? icondir->entries[c].res_info.icon.width : icondir->entries[c].res_info.cursor.width),
+ (is_icon ? icondir->entries[c].res_info.icon.height : icondir->entries[c].res_info.cursor.height),
+ icondir->entries[c].plane_count,
+ icondir->entries[c].bit_count);*/
+
+ /* find the corresponding icon resource */
+ snprintf(name, sizeof(name)/sizeof(char), "-%d", icondir->entries[c].res_id);
+ fwr = find_resource(fi, (is_icon ? "-3" : "-1"), name, lang, &level);
+ if (fwr == NULL) {
+ error("%s: could not find `%s' in `%s' resource.",
+ fi->file->name(), &name[1], (is_icon ? "group_icon" : "group_cursor"));
+ return NULL;
+ }
+
+ if (get_resource_entry(fi, fwr, &iconsize) != NULL) {
+ if (iconsize == 0) {
+ debugC(DEBUG_RESOURCE, "%s: icon resource `%s' is empty, skipping", fi->file->name(), name);
+ skipped++;
+ continue;
+ }
+ if ((uint32)iconsize != icondir->entries[c].bytes_in_res) {
+ debugC(DEBUG_RESOURCE, "%s: mismatch of size in icon resource `%s' and group (%d != %d)",
+ fi->file->name(), name, iconsize, icondir->entries[c].bytes_in_res);
+ }
+ size += iconsize; /* size += icondir->entries[c].bytes_in_res; */
+
+ /* cursor resources have two additional WORDs that contain
+ * hotspot info */
+ if (!is_icon)
+ size -= sizeof(uint16)*2;
+ }
+ }
+ offset = sizeof(Win32CursorIconFileDir) + (icondir->count-skipped) * sizeof(Win32CursorIconFileDirEntry);
+ size += offset;
+ *ressize = size;
+
+ /* allocate that much memory */
+ memory = (byte *)malloc(size);
+ fileicondir = (Win32CursorIconFileDir *)memory;
+
+ /* transfer Win32CursorIconDir structure members */
+ fileicondir->reserved = icondir->reserved;
+ fileicondir->type = icondir->type;
+ fileicondir->count = icondir->count - skipped;
+
+ /* transfer each cursor/icon: Win32CursorIconDirEntry and data */
+ skipped = 0;
+ for (c = 0 ; c < icondir->count ; c++) {
+ int level;
+ char name[14];
+ WinResource *fwr;
+ byte *data;
+
+ /* find the corresponding icon resource */
+ snprintf(name, sizeof(name)/sizeof(char), "-%d", icondir->entries[c].res_id);
+ fwr = find_resource(fi, (is_icon ? "-3" : "-1"), name, lang, &level);
+ if (fwr == NULL) {
+ error("%s: could not find `%s' in `%s' resource.",
+ fi->file->name(), &name[1], (is_icon ? "group_icon" : "group_cursor"));
+ return NULL;
+ }
+
+ /* get data and size of that resource */
+ data = (byte *)get_resource_entry(fi, fwr, &size);
+ if (data == NULL) {
+ /* get_resource_entry has printed error */
+ return NULL;
+ }
+ if (size == 0) {
+ skipped++;
+ continue;
+ }
+
+ /* copy ICONDIRENTRY (not including last dwImageOffset) */
+ memcpy(&fileicondir->entries[c-skipped], &icondir->entries[c],
+ sizeof(Win32CursorIconFileDirEntry)-sizeof(uint32));
+
+ /* special treatment for cursors */
+ if (!is_icon) {
+ fileicondir->entries[c-skipped].width = icondir->entries[c].res_info.cursor.width;
+ fileicondir->entries[c-skipped].height = icondir->entries[c].res_info.cursor.height / 2;
+ fileicondir->entries[c-skipped].color_count = 0;
+ fileicondir->entries[c-skipped].reserved = 0;
+ }
+
+ /* set image offset and increase it */
+ fileicondir->entries[c-skipped].dib_offset = offset;
+
+ /* transfer resource into file memory */
+ if (is_icon) {
+ memcpy(&memory[offset], data, icondir->entries[c].bytes_in_res);
+ } else {
+ fileicondir->entries[c-skipped].hotspot_x = ((uint16 *) data)[0];
+ fileicondir->entries[c-skipped].hotspot_y = ((uint16 *) data)[1];
+ memcpy(&memory[offset], data+sizeof(uint16)*2,
+ icondir->entries[c].bytes_in_res-sizeof(uint16)*2);
+ offset -= sizeof(uint16)*2;
+ }
+
+ /* increase the offset pointer */
+ offset += icondir->entries[c].bytes_in_res;
+ }
+
+ return memory;
+}
+
+/* check_offset:
+ * Check if a chunk of data (determined by offset and size)
+ * is within the bounds of the WinLibrary file.
+ * Usually not called directly.
+ */
+bool Win32ResExtractor::check_offset(byte *memory, int total_size, const char *name, void *offset, int size) {
+ int need_size = (int)((byte *)offset - memory + size);
+
+ debugC(DEBUG_RESOURCE, "check_offset: size=%x vs %x offset=%x size=%x",
+ need_size, total_size, (byte *)offset - memory, size);
+
+ if (need_size < 0 || need_size > total_size) {
+ error("%s: premature end", name);
+ return false;
+ }
+
+ return true;
+}
+
+
+/* do_resources:
+ * Do something for each resource matching type, name and lang.
+ */
+int Win32ResExtractor::do_resources(WinLibrary *fi, const char *type, char *name, char *lang, int action, byte **data) {
+ WinResource *type_wr;
+ WinResource *name_wr;
+ WinResource *lang_wr;
+ int size;
+
+ type_wr = (WinResource *)calloc(sizeof(WinResource)*3, 1);
+ name_wr = type_wr + 1;
+ lang_wr = type_wr + 2;
+
+ size = do_resources_recurs(fi, NULL, type_wr, name_wr, lang_wr, type, name, lang, action, data);
+
+ free(type_wr);
+
+ return size;
+}
+
+/* what is each entry in this directory level for? type, name or language? */
+#define WINRESOURCE_BY_LEVEL(x) ((x)==0 ? type_wr : ((x)==1 ? name_wr : lang_wr))
+
+/* does the id of this entry match the specified id? */
+#define LEVEL_MATCHES(x) (x == NULL || x ## _wr->id[0] == '\0' || compare_resource_id(x ## _wr, x))
+
+int Win32ResExtractor::do_resources_recurs(WinLibrary *fi, WinResource *base,
+ WinResource *type_wr, WinResource *name_wr, WinResource *lang_wr,
+ const char *type, char *name, char *lang, int action, byte **data) {
+ int c, rescnt;
+ WinResource *wr;
+ uint32 size = 0;
+
+ /* get a list of all resources at this level */
+ wr = list_resources(fi, base, &rescnt);
+ if (wr == NULL)
+ if (size != 0)
+ return size;
+ else
+ return 0;
+
+ /* process each resource listed */
+ for (c = 0 ; c < rescnt ; c++) {
+ /* (over)write the corresponding WinResource holder with the current */
+ memcpy(WINRESOURCE_BY_LEVEL(wr[c].level), wr+c, sizeof(WinResource));
+
+ /* go deeper unless there is something that does NOT match */
+ if (LEVEL_MATCHES(type) && LEVEL_MATCHES(name) && LEVEL_MATCHES(lang)) {
+ if (wr->is_directory)
+ size = do_resources_recurs(fi, wr+c, type_wr, name_wr, lang_wr, type, name, lang, action, data);
+ else
+ size = extract_resources(fi, wr+c, type_wr, name_wr, lang_wr, data);
+ }
+ }
+
+ /* since we're moving back one level after this, unset the
+ * WinResource holder used on this level */
+ memset(WINRESOURCE_BY_LEVEL(wr[0].level), 0, sizeof(WinResource));
+
+ return size;
+}
+
+/* return the resource id quoted if it's a string, otherwise just return it */
+char *Win32ResExtractor::get_resource_id_quoted(WinResource *wr) {
+ static char tmp[WINRES_ID_MAXLEN+2];
+
+ if (wr->numeric_id || wr->id[0] == '\0')
+ return wr->id;
+
+ sprintf(tmp, "'%s'", wr->id);
+ return tmp;
+}
+
+bool Win32ResExtractor::compare_resource_id(WinResource *wr, const char *id) {
+ if (wr->numeric_id) {
+ int32 cmp1, cmp2;
+ if (id[0] == '+')
+ return false;
+ if (id[0] == '-')
+ id++;
+ if (!(cmp1 = strtol(wr->id, 0, 10)) || !(cmp2 = strtol(id, 0, 10)) || cmp1 != cmp2)
+ return false;
+ } else {
+ if (id[0] == '-')
+ return false;
+ if (id[0] == '+')
+ id++;
+ if (strcmp(wr->id, id))
+ return false;
+ }
+
+ return true;
+}
+
+bool Win32ResExtractor::decode_pe_resource_id(WinLibrary *fi, WinResource *wr, uint32 value) {
+ if (value & IMAGE_RESOURCE_NAME_IS_STRING) { /* numeric id */
+ int c, len;
+ uint16 *mem = (uint16 *)
+ (fi->first_resource + (value & ~IMAGE_RESOURCE_NAME_IS_STRING));
+
+ /* copy each char of the string, and terminate it */
+ RETURN_IF_BAD_POINTER(false, *mem);
+ len = mem[0];
+ RETURN_IF_BAD_OFFSET(false, &mem[1], sizeof(uint16) * len);
+
+ len = MIN(mem[0], (uint16)WINRES_ID_MAXLEN);
+ for (c = 0 ; c < len ; c++)
+ wr->id[c] = mem[c+1] & 0x00FF;
+ wr->id[len] = '\0';
+ } else { /* Unicode string id */
+ /* translate id into a string */
+ snprintf(wr->id, WINRES_ID_MAXLEN, "%d", value);
+ }
+
+ wr->numeric_id = (value & IMAGE_RESOURCE_NAME_IS_STRING ? false:true);
+ return true;
+}
+
+byte *Win32ResExtractor::get_resource_entry(WinLibrary *fi, WinResource *wr, int *size) {
+ if (fi->is_PE_binary) {
+ Win32ImageResourceDataEntry *dataent;
+
+ dataent = (Win32ImageResourceDataEntry *) wr->children;
+ RETURN_IF_BAD_POINTER(NULL, *dataent);
+ *size = dataent->size;
+ RETURN_IF_BAD_OFFSET(NULL, fi->memory + dataent->offset_to_data, *size);
+
+ return fi->memory + dataent->offset_to_data;
+ } else {
+ Win16NENameInfo *nameinfo;
+ int sizeshift;
+
+ nameinfo = (Win16NENameInfo *) wr->children;
+ sizeshift = *((uint16 *) fi->first_resource - 1);
+ *size = nameinfo->length << sizeshift;
+ RETURN_IF_BAD_OFFSET(NULL, fi->memory + (nameinfo->offset << sizeshift), *size);
+
+ return fi->memory + (nameinfo->offset << sizeshift);
+ }
+}
+
+bool Win32ResExtractor::decode_ne_resource_id(WinLibrary *fi, WinResource *wr, uint16 value) {
+ if (value & NE_RESOURCE_NAME_IS_NUMERIC) { /* numeric id */
+ /* translate id into a string */
+ snprintf(wr->id, WINRES_ID_MAXLEN, "%d", value & ~NE_RESOURCE_NAME_IS_NUMERIC);
+ } else { /* ASCII string id */
+ int len;
+ char *mem = (char *)NE_HEADER(fi->memory)
+ + NE_HEADER(fi->memory)->rsrctab
+ + value;
+
+ /* copy each char of the string, and terminate it */
+ RETURN_IF_BAD_POINTER(false, *mem);
+ len = mem[0];
+ RETURN_IF_BAD_OFFSET(false, &mem[1], sizeof(char) * len);
+ memcpy(wr->id, &mem[1], len);
+ wr->id[len] = '\0';
+ }
+
+ wr->numeric_id = (value & NE_RESOURCE_NAME_IS_NUMERIC ? true:false);
+ return true;
+}
+
+Win32ResExtractor::WinResource *Win32ResExtractor::list_pe_resources(WinLibrary *fi, Win32ImageResourceDirectory *pe_res, int level, int *count) {
+ WinResource *wr;
+ int c, rescnt;
+ Win32ImageResourceDirectoryEntry *dirent
+ = (Win32ImageResourceDirectoryEntry *)(pe_res + 1);
+
+ /* count number of `type' resources */
+ RETURN_IF_BAD_POINTER(NULL, *dirent);
+ rescnt = pe_res->number_of_named_entries + pe_res->number_of_id_entries;
+ *count = rescnt;
+
+ /* allocate WinResource's */
+ wr = (WinResource *)malloc(sizeof(WinResource) * rescnt);
+
+ /* fill in the WinResource's */
+ for (c = 0 ; c < rescnt ; c++) {
+ RETURN_IF_BAD_POINTER(NULL, dirent[c]);
+ wr[c].this_ = pe_res;
+ wr[c].level = level;
+ wr[c].is_directory = (dirent[c].u2.s.data_is_directory);
+ wr[c].children = fi->first_resource + dirent[c].u2.s.offset_to_directory;
+
+ /* fill in wr->id, wr->numeric_id */
+ if (!decode_pe_resource_id (fi, wr + c, dirent[c].u1.name))
+ return NULL;
+ }
+
+ return wr;
+}
+
+Win32ResExtractor::WinResource *Win32ResExtractor::list_ne_name_resources(WinLibrary *fi, WinResource *typeres, int *count) {
+ int c, rescnt;
+ WinResource *wr;
+ Win16NETypeInfo *typeinfo = (Win16NETypeInfo *) typeres->this_;
+ Win16NENameInfo *nameinfo = (Win16NENameInfo *) typeres->children;
+
+ /* count number of `type' resources */
+ RETURN_IF_BAD_POINTER(NULL, typeinfo->count);
+ *count = rescnt = typeinfo->count;
+
+ /* allocate WinResource's */
+ wr = (WinResource *)malloc(sizeof(WinResource) * rescnt);
+
+ /* fill in the WinResource's */
+ for (c = 0 ; c < rescnt ; c++) {
+ RETURN_IF_BAD_POINTER(NULL, nameinfo[c]);
+ wr[c].this_ = nameinfo+c;
+ wr[c].is_directory = false;
+ wr[c].children = nameinfo+c;
+ wr[c].level = 1;
+
+ /* fill in wr->id, wr->numeric_id */
+ if (!decode_ne_resource_id(fi, wr + c, (nameinfo+c)->id))
+ return NULL;
+ }
+
+ return wr;
+}
+
+Win32ResExtractor::WinResource *Win32ResExtractor::list_ne_type_resources(WinLibrary *fi, int *count) {
+ int c, rescnt;
+ WinResource *wr;
+ Win16NETypeInfo *typeinfo;
+
+ /* count number of `type' resources */
+ typeinfo = (Win16NETypeInfo *) fi->first_resource;
+ RETURN_IF_BAD_POINTER(NULL, *typeinfo);
+ for (rescnt = 0 ; typeinfo->type_id != 0 ; rescnt++) {
+ typeinfo = NE_TYPEINFO_NEXT(typeinfo);
+ RETURN_IF_BAD_POINTER(NULL, *typeinfo);
+ }
+ *count = rescnt;
+
+ /* allocate WinResource's */
+ wr = (WinResource *)malloc(sizeof(WinResource) * rescnt);
+
+ /* fill in the WinResource's */
+ typeinfo = (Win16NETypeInfo *) fi->first_resource;
+ for (c = 0 ; c < rescnt ; c++) {
+ wr[c].this_ = typeinfo;
+ wr[c].is_directory = (typeinfo->count != 0);
+ wr[c].children = typeinfo+1;
+ wr[c].level = 0;
+
+ /* fill in wr->id, wr->numeric_id */
+ if (!decode_ne_resource_id(fi, wr + c, typeinfo->type_id))
+ return NULL;
+
+ typeinfo = NE_TYPEINFO_NEXT(typeinfo);
+ }
+
+ return wr;
+}
+
+/* list_resources:
+ * Return an array of WinResource's in the current
+ * resource level specified by res.
+ */
+Win32ResExtractor::WinResource *Win32ResExtractor::list_resources(WinLibrary *fi, WinResource *res, int *count) {
+ if (res != NULL && !res->is_directory)
+ return NULL;
+
+ if (fi->is_PE_binary) {
+ return list_pe_resources(fi, (Win32ImageResourceDirectory *)
+ (res == NULL ? fi->first_resource : res->children),
+ (res == NULL ? 0 : res->level+1),
+ count);
+ } else {
+ return (res == NULL
+ ? list_ne_type_resources(fi, count)
+ : list_ne_name_resources(fi, res, count));
+ }
+}
+
+/* read_library:
+ * Read header and get resource directory offset in a Windows library
+ * (AKA module).
+ *
+ */
+bool Win32ResExtractor::read_library(WinLibrary *fi) {
+ /* check for DOS header signature `MZ' */
+ RETURN_IF_BAD_POINTER(false, MZ_HEADER(fi->memory)->magic);
+ if (MZ_HEADER(fi->memory)->magic == IMAGE_DOS_SIGNATURE) {
+ DOSImageHeader *mz_header = MZ_HEADER(fi->memory);
+
+ RETURN_IF_BAD_POINTER(false, mz_header->lfanew);
+ if (mz_header->lfanew < sizeof(DOSImageHeader)) {
+ error("%s: not a Windows library", fi->file->name());
+ return false;
+ }
+ }
+
+ /* check for OS2 (Win16) header signature `NE' */
+ RETURN_IF_BAD_POINTER(false, NE_HEADER(fi->memory)->magic);
+ if (NE_HEADER(fi->memory)->magic == IMAGE_OS2_SIGNATURE) {
+ OS2ImageHeader *header = NE_HEADER(fi->memory);
+
+ RETURN_IF_BAD_POINTER(false, header->rsrctab);
+ RETURN_IF_BAD_POINTER(false, header->restab);
+ if (header->rsrctab >= header->restab) {
+ error("%s: no resource directory found", fi->file->name());
+ return false;
+ }
+
+ fi->is_PE_binary = false;
+ fi->first_resource = (byte *) NE_HEADER(fi->memory)
+ + header->rsrctab + sizeof(uint16);
+ RETURN_IF_BAD_POINTER(false, *(Win16NETypeInfo *) fi->first_resource);
+
+ return true;
+ }
+
+ /* check for NT header signature `PE' */
+ RETURN_IF_BAD_POINTER(false, PE_HEADER(fi->memory)->signature);
+ if (PE_HEADER(fi->memory)->signature == IMAGE_NT_SIGNATURE) {
+ Win32ImageSectionHeader *pe_sec;
+ Win32ImageDataDirectory *dir;
+ Win32ImageNTHeaders *pe_header;
+ int d;
+
+ /* allocate new memory */
+ fi->total_size = calc_vma_size(fi);
+ if (fi->total_size == 0) {
+ /* calc_vma_size has reported error */
+ return false;
+ }
+ fi->memory = (byte *)realloc(fi->memory, fi->total_size);
+
+ /* relocate memory, start from last section */
+ pe_header = PE_HEADER(fi->memory);
+ RETURN_IF_BAD_POINTER(false, pe_header->file_header.number_of_sections);
+
+ /* we don't need to do OFFSET checking for the sections.
+ * calc_vma_size has already done that */
+ for (d = pe_header->file_header.number_of_sections - 1; d >= 0 ; d--) {
+ pe_sec = PE_SECTIONS(fi->memory) + d;
+
+ if (pe_sec->characteristics & IMAGE_SCN_CNT_UNINITIALIZED_DATA)
+ continue;
+
+ //if (pe_sec->virtual_address + pe_sec->size_of_raw_data > fi->total_size)
+
+ RETURN_IF_BAD_OFFSET(0, fi->memory + pe_sec->virtual_address, pe_sec->size_of_raw_data);
+ RETURN_IF_BAD_OFFSET(0, fi->memory + pe_sec->pointer_to_raw_data, pe_sec->size_of_raw_data);
+ if (pe_sec->virtual_address != pe_sec->pointer_to_raw_data) {
+ memmove(fi->memory + pe_sec->virtual_address,
+ fi->memory + pe_sec->pointer_to_raw_data,
+ pe_sec->size_of_raw_data);
+ }
+ }
+
+ /* find resource directory */
+ RETURN_IF_BAD_POINTER(false, pe_header->optional_header.data_directory[IMAGE_DIRECTORY_ENTRY_RESOURCE]);
+ dir = pe_header->optional_header.data_directory + IMAGE_DIRECTORY_ENTRY_RESOURCE;
+ if (dir->size == 0) {
+ error("%s: file contains no resources", fi->file->name());
+ return false;
+ }
+
+ fi->first_resource = fi->memory + dir->virtual_address;
+ fi->is_PE_binary = true;
+ return true;
+ }
+
+ /* other (unknown) header signature was found */
+ error("%s: not a Windows library", fi->file->name());
+ return false;
+}
+
+/* calc_vma_size:
+ * Calculate the total amount of memory needed for a 32-bit Windows
+ * module. Returns -1 if file was too small.
+ */
+int Win32ResExtractor::calc_vma_size(WinLibrary *fi) {
+ Win32ImageSectionHeader *seg;
+ int c, segcount, size;
+
+ size = 0;
+ RETURN_IF_BAD_POINTER(-1, PE_HEADER(fi->memory)->file_header.number_of_sections);
+ segcount = PE_HEADER(fi->memory)->file_header.number_of_sections;
+
+ /* If there are no segments, just process file like it is.
+ * This is (probably) not the right thing to do, but problems
+ * will be delt with later anyway.
+ */
+ if (segcount == 0)
+ return fi->total_size;
+
+ seg = PE_SECTIONS(fi->memory);
+ RETURN_IF_BAD_POINTER(-1, *seg);
+ for (c = 0 ; c < segcount ; c++) {
+ RETURN_IF_BAD_POINTER(0, *seg);
+
+ size = MAX((uint32)size, seg->virtual_address + seg->size_of_raw_data);
+ /* I have no idea what misc.virtual_size is for... */
+ size = MAX((uint32)size, seg->virtual_address + seg->misc.virtual_size);
+ seg++;
+ }
+
+ return size;
+}
+
+Win32ResExtractor::WinResource *Win32ResExtractor::find_with_resource_array(WinLibrary *fi, WinResource *wr, const char *id) {
+ int c, rescnt;
+ WinResource *return_wr;
+
+ wr = list_resources(fi, wr, &rescnt);
+ if (wr == NULL)
+ return NULL;
+
+ for (c = 0 ; c < rescnt ; c++) {
+ if (compare_resource_id(&wr[c], id)) {
+ /* duplicate WinResource and return it */
+ return_wr = (WinResource *)malloc(sizeof(WinResource));
+ memcpy(return_wr, &wr[c], sizeof(WinResource));
+
+ /* free old WinResource */
+ free(wr);
+ return return_wr;
+ }
+ }
+
+ return NULL;
+}
+
+Win32ResExtractor::WinResource *Win32ResExtractor::find_resource(WinLibrary *fi, const char *type, const char *name, const char *language, int *level) {
+ WinResource *wr;
+
+ *level = 0;
+ if (type == NULL)
+ return NULL;
+ wr = find_with_resource_array(fi, NULL, type);
+ if (wr == NULL || !wr->is_directory)
+ return wr;
+
+ *level = 1;
+ if (name == NULL)
+ return wr;
+ wr = find_with_resource_array(fi, wr, name);
+ if (wr == NULL || !wr->is_directory)
+ return wr;
+
+ *level = 2;
+ if (language == NULL)
+ return wr;
+ wr = find_with_resource_array(fi, wr, language);
+ return wr;
+}
+
+#define ROW_BYTES(bits) ((((bits) + 31) >> 5) << 2)
+
+
+int Win32ResExtractor::convertIcons(byte *data, int datasize, byte **cursor, int *w, int *h,
+ int *hotspot_x, int *hotspot_y, int *keycolor, byte **pal, int *palSize) {
+ Win32CursorIconFileDir dir;
+ Win32CursorIconFileDirEntry *entries = NULL;
+ uint32 offset;
+ uint32 c, d;
+ int completed;
+ int matched = 0;
+ MemoryReadStream *in = new MemoryReadStream(data, datasize);
+
+ if (!in->read(&dir, sizeof(Win32CursorIconFileDir)- sizeof(Win32CursorIconFileDirEntry)))
+ goto cleanup;
+ fix_win32_cursor_icon_file_dir_endian(&dir);
+
+ if (dir.reserved != 0) {
+ error("not an icon or cursor file (reserved non-zero)");
+ goto cleanup;
+ }
+ if (dir.type != 1 && dir.type != 2) {
+ error("not an icon or cursor file (wrong type)");
+ goto cleanup;
+ }
+
+ entries = (Win32CursorIconFileDirEntry *)malloc(dir.count * sizeof(Win32CursorIconFileDirEntry));
+ for (c = 0; c < dir.count; c++) {
+ if (!in->read(&entries[c], sizeof(Win32CursorIconFileDirEntry)))
+ goto cleanup;
+ fix_win32_cursor_icon_file_dir_entry_endian(&entries[c]);
+ if (entries[c].reserved != 0)
+ error("reserved is not zero");
+ }
+
+ offset = sizeof(Win32CursorIconFileDir) + (dir.count - 1) * (sizeof(Win32CursorIconFileDirEntry));
+
+ for (completed = 0; completed < dir.count; ) {
+ uint32 min_offset = 0x7fffffff;
+ int previous = completed;
+
+ for (c = 0; c < dir.count; c++) {
+ if (entries[c].dib_offset == offset) {
+ Win32BitmapInfoHeader bitmap;
+ Win32RGBQuad *palette = NULL;
+ uint32 palette_count = 0;
+ uint32 image_size, mask_size;
+ uint32 width, height;
+ byte *image_data = NULL, *mask_data = NULL;
+ byte *row = NULL;
+
+ if (!in->read(&bitmap, sizeof(Win32BitmapInfoHeader)))
+ goto local_cleanup;
+
+ fix_win32_bitmap_info_header_endian(&bitmap);
+ if (bitmap.size < sizeof(Win32BitmapInfoHeader)) {
+ error("bitmap header is too short");
+ goto local_cleanup;
+ }
+ if (bitmap.compression != 0) {
+ error("compressed image data not supported");
+ goto local_cleanup;
+ }
+ if (bitmap.x_pels_per_meter != 0)
+ error("x_pels_per_meter field in bitmap should be zero");
+ if (bitmap.y_pels_per_meter != 0)
+ error("y_pels_per_meter field in bitmap should be zero");
+ if (bitmap.clr_important != 0)
+ error("clr_important field in bitmap should be zero");
+ if (bitmap.planes != 1)
+ error("planes field in bitmap should be one");
+ if (bitmap.size != sizeof(Win32BitmapInfoHeader)) {
+ uint32 skip = bitmap.size - sizeof(Win32BitmapInfoHeader);
+ error("skipping %d bytes of extended bitmap header", skip);
+ in->seek(skip, SEEK_CUR);
+ }
+ offset += bitmap.size;
+
+ if (bitmap.clr_used != 0 || bitmap.bit_count < 24) {
+ palette_count = (bitmap.clr_used != 0 ? bitmap.clr_used : 1 << bitmap.bit_count);
+ palette = (Win32RGBQuad *)malloc(sizeof(Win32RGBQuad) * palette_count);
+ if (!in->read(palette, sizeof(Win32RGBQuad) * palette_count))
+ goto local_cleanup;
+ offset += sizeof(Win32RGBQuad) * palette_count;
+ }
+
+ width = bitmap.width;
+ height = ABS(bitmap.height)/2;
+
+ image_size = height * ROW_BYTES(width * bitmap.bit_count);
+ mask_size = height * ROW_BYTES(width);
+
+ if (entries[c].dib_size != bitmap.size + image_size + mask_size + palette_count * sizeof(Win32RGBQuad))
+ debugC(DEBUG_RESOURCE, "incorrect total size of bitmap (%d specified; %d real)",
+ entries[c].dib_size,
+ bitmap.size + image_size + mask_size + palette_count * sizeof(Win32RGBQuad)
+ );
+
+ image_data = (byte *)malloc(image_size);
+ if (!in->read(image_data, image_size))
+ goto local_cleanup;
+
+ mask_data = (byte *)malloc(mask_size);
+ if (!in->read(mask_data, mask_size))
+ goto local_cleanup;
+
+ offset += image_size;
+ offset += mask_size;
+ completed++;
+ matched++;
+
+ *hotspot_x = entries[c].hotspot_x;
+ *hotspot_y = entries[c].hotspot_y;
+ *w = width;
+ *h = height;
+ *keycolor = 0;
+ *cursor = (byte *)malloc(width * height);
+
+ row = (byte *)malloc(width * 4);
+
+ for (d = 0; d < height; d++) {
+ uint32 x;
+ uint32 y = (bitmap.height < 0 ? d : height - d - 1);
+ uint32 imod = y * (image_size / height) * 8 / bitmap.bit_count;
+ //uint32 mmod = y * (mask_size / height) * 8;
+
+ for (x = 0; x < width; x++) {
+
+ uint32 color = simple_vec(image_data, x + imod, bitmap.bit_count);
+
+ // FIXME?: This works only with b/w cursors and white index may be
+ // different. But now it's enough.
+ if (color) {
+ cursor[0][width * d + x] = 15; // white in SCUMM
+ } else {
+ cursor[0][width * d + x] = 255; // transparent
+ }
+ /*
+
+ if (bitmap.bit_count <= 16) {
+ if (color >= palette_count) {
+ error("color out of range in image data");
+ goto local_cleanup;
+ }
+ row[4*x+0] = palette[color].red;
+ row[4*x+1] = palette[color].green;
+ row[4*x+2] = palette[color].blue;
+
+ } else {
+ row[4*x+0] = (color >> 16) & 0xFF;
+ row[4*x+1] = (color >> 8) & 0xFF;
+ row[4*x+2] = (color >> 0) & 0xFF;
+ }
+ if (bitmap.bit_count == 32)
+ row[4*x+3] = (color >> 24) & 0xFF;
+ else
+ row[4*x+3] = simple_vec(mask_data, x + mmod, 1) ? 0 : 0xFF;
+ */
+ }
+
+ }
+
+ if (row != NULL)
+ free(row);
+ if (palette != NULL)
+ free(palette);
+ if (image_data != NULL) {
+ free(image_data);
+ free(mask_data);
+ }
+ continue;
+
+ local_cleanup:
+
+ if (row != NULL)
+ free(row);
+ if (palette != NULL)
+ free(palette);
+ if (image_data != NULL) {
+ free(image_data);
+ free(mask_data);
+ }
+ goto cleanup;
+ } else {
+ if (entries[c].dib_offset > offset)
+ min_offset = MIN(min_offset, entries[c].dib_offset);
+ }
+ }
+
+ if (previous == completed) {
+ if (min_offset < offset) {
+ error("offset of bitmap header incorrect (too low)");
+ goto cleanup;
+ }
+ debugC(DEBUG_RESOURCE, "skipping %d bytes of garbage at %d", min_offset-offset, offset);
+ in->seek(min_offset - offset, SEEK_CUR);
+ offset = min_offset;
+ }
+ }
+
+ free(entries);
+ return matched;
+
+cleanup:
+
+ free(entries);
+ return -1;
+}
+
+uint32 Win32ResExtractor::simple_vec(byte *data, uint32 ofs, byte size) {
+ switch (size) {
+ case 1:
+ return (data[ofs/8] >> (7 - ofs%8)) & 1;
+ case 2:
+ return (data[ofs/4] >> ((3 - ofs%4) << 1)) & 3;
+ case 4:
+ return (data[ofs/2] >> ((1 - ofs%2) << 2)) & 15;
+ case 8:
+ return data[ofs];
+ case 16:
+ return data[2*ofs] | data[2*ofs+1] << 8;
+ case 24:
+ return data[3*ofs] | data[3*ofs+1] << 8 | data[3*ofs+2] << 16;
+ case 32:
+ return data[4*ofs] | data[4*ofs+1] << 8 | data[4*ofs+2] << 16 | data[4*ofs+3] << 24;
+ }
+
+ return 0;
+}
+
+#define LE16(x) ((x) = TO_LE_16(x))
+#define LE32(x) ((x) = TO_LE_32(x))
+
+void Win32ResExtractor::fix_win32_cursor_icon_file_dir_endian(Win32CursorIconFileDir *obj) {
+ LE16(obj->reserved);
+ LE16(obj->type);
+ LE16(obj->count);
+}
+
+void Win32ResExtractor::fix_win32_bitmap_info_header_endian(Win32BitmapInfoHeader *obj) {
+ LE32(obj->size);
+ LE32(obj->width);
+ LE32(obj->height);
+ LE16(obj->planes);
+ LE16(obj->bit_count);
+ LE32(obj->compression);
+ LE32(obj->size_image);
+ LE32(obj->x_pels_per_meter);
+ LE32(obj->y_pels_per_meter);
+ LE32(obj->clr_used);
+ LE32(obj->clr_important);
+}
+
+void Win32ResExtractor::fix_win32_cursor_icon_file_dir_entry_endian(Win32CursorIconFileDirEntry *obj) {
+ LE16(obj->hotspot_x);
+ LE16(obj->hotspot_y);
+ LE32(obj->dib_size);
+ LE32(obj->dib_offset);
+}
+
+void Win32ResExtractor::fix_win32_image_section_header(Win32ImageSectionHeader *obj) {
+ LE32(obj->misc.physical_address);
+ LE32(obj->virtual_address);
+ LE32(obj->size_of_raw_data);
+ LE32(obj->pointer_to_raw_data);
+ LE32(obj->pointer_to_relocations);
+ LE32(obj->pointer_to_linenumbers);
+ LE16(obj->number_of_relocations);
+ LE16(obj->number_of_linenumbers);
+ LE32(obj->characteristics);
+}
+
+void Win32ResExtractor::fix_os2_image_header_endian(OS2ImageHeader *obj) {
+ LE16(obj->magic);
+ LE16(obj->enttab);
+ LE16(obj->cbenttab);
+ LE32(obj->crc);
+ LE16(obj->flags);
+ LE16(obj->autodata);
+ LE16(obj->heap);
+ LE16(obj->stack);
+ LE32(obj->csip);
+ LE32(obj->sssp);
+ LE16(obj->cseg);
+ LE16(obj->cmod);
+ LE16(obj->cbnrestab);
+ LE16(obj->segtab);
+ LE16(obj->rsrctab);
+ LE16(obj->restab);
+ LE16(obj->modtab);
+ LE16(obj->imptab);
+ LE32(obj->nrestab);
+ LE16(obj->cmovent);
+ LE16(obj->align);
+ LE16(obj->cres);
+ LE16(obj->fastload_offset);
+ LE16(obj->fastload_length);
+ LE16(obj->swaparea);
+ LE16(obj->expver);
+}
+
+/* fix_win32_image_header_endian:
+ * NOTE: This assumes that the optional header is always available.
+ */
+void Win32ResExtractor::fix_win32_image_header_endian(Win32ImageNTHeaders *obj) {
+ LE32(obj->signature);
+ LE16(obj->file_header.machine);
+ LE16(obj->file_header.number_of_sections);
+ LE32(obj->file_header.time_date_stamp);
+ LE32(obj->file_header.pointer_to_symbol_table);
+ LE32(obj->file_header.number_of_symbols);
+ LE16(obj->file_header.size_of_optional_header);
+ LE16(obj->file_header.characteristics);
+ LE16(obj->optional_header.magic);
+ LE32(obj->optional_header.size_of_code);
+ LE32(obj->optional_header.size_of_initialized_data);
+ LE32(obj->optional_header.size_of_uninitialized_data);
+ LE32(obj->optional_header.address_of_entry_point);
+ LE32(obj->optional_header.base_of_code);
+ LE32(obj->optional_header.base_of_data);
+ LE32(obj->optional_header.image_base);
+ LE32(obj->optional_header.section_alignment);
+ LE32(obj->optional_header.file_alignment);
+ LE16(obj->optional_header.major_operating_system_version);
+ LE16(obj->optional_header.minor_operating_system_version);
+ LE16(obj->optional_header.major_image_version);
+ LE16(obj->optional_header.minor_image_version);
+ LE16(obj->optional_header.major_subsystem_version);
+ LE16(obj->optional_header.minor_subsystem_version);
+ LE32(obj->optional_header.win32_version_value);
+ LE32(obj->optional_header.size_of_image);
+ LE32(obj->optional_header.size_of_headers);
+ LE32(obj->optional_header.checksum);
+ LE16(obj->optional_header.subsystem);
+ LE16(obj->optional_header.dll_characteristics);
+ LE32(obj->optional_header.size_of_stack_reserve);
+ LE32(obj->optional_header.size_of_stack_commit);
+ LE32(obj->optional_header.size_of_heap_reserve);
+ LE32(obj->optional_header.size_of_heap_commit);
+ LE32(obj->optional_header.loader_flags);
+ LE32(obj->optional_header.number_of_rva_and_sizes);
+}
+
+void Win32ResExtractor::fix_win32_image_data_directory(Win32ImageDataDirectory *obj) {
+ LE32(obj->virtual_address);
+ LE32(obj->size);
+}
+
+
+MacResExtractor::MacResExtractor(ScummEngine_v70he *scumm) : ResExtractor(scumm) {
+ _resOffset = -1;
+}
+
+int MacResExtractor::extractResource(int id, byte **buf) {
+ Common::File in;
+ int size;
+
+ if (!_fileName[0]) // We are running for the first time
+ if (_vm->_substResFileNameIndex > 0) {
+ char buf1[128];
+
+ snprintf(buf1, 128, "%s.he3", _vm->getBaseName());
+ _vm->generateSubstResFileName(buf1, _fileName, sizeof(buf1));
+
+ // Some programs write it as .bin. Try that too
+ if (!in.exists(_fileName)) {
+ strcpy(buf1, _fileName);
+ snprintf(_fileName, 128, "%s.bin", buf1);
+
+ if (!in.exists(_fileName)) {
+ // And finally check if we have dumped resource fork
+ snprintf(_fileName, 128, "%s.rsrc", buf1);
+ if (!in.exists(_fileName)) {
+ error("Cannot open file any of files '%s', '%s.bin', '%s.rsrc",
+ buf1, buf1, buf1);
+ }
+ }
+ }
+ }
+
+ in.open(_fileName);
+ if (!in.isOpen()) {
+ error("Cannot open file %s", _fileName);
+ }
+
+ // we haven't calculated it
+ if (_resOffset == -1) {
+ if (!init(in))
+ error("Resource fork is missing in file '%s'", _fileName);
+ in.close();
+ in.open(_fileName);
+ }
+
+ *buf = getResource(in, "crsr", 1000 + id, &size);
+
+ in.close();
+
+ if (*buf == NULL)
+ error("There is no cursor ID #%d", 1000 + id);
+
+ return size;
+}
+
+#define MBI_INFOHDR 128
+#define MBI_ZERO1 0
+#define MBI_NAMELEN 1
+#define MBI_ZERO2 74
+#define MBI_ZERO3 82
+#define MBI_DFLEN 83
+#define MBI_RFLEN 87
+#define MAXNAMELEN 63
+
+bool MacResExtractor::init(Common::File in) {
+ byte infoHeader[MBI_INFOHDR];
+ int32 data_size, rsrc_size;
+ int32 data_size_pad, rsrc_size_pad;
+ int filelen;
+
+ filelen = in.size();
+ in.read(infoHeader, MBI_INFOHDR);
+
+ // Maybe we have MacBinary?
+ if (infoHeader[MBI_ZERO1] == 0 && infoHeader[MBI_ZERO2] == 0 &&
+ infoHeader[MBI_ZERO3] == 0 && infoHeader[MBI_NAMELEN] <= MAXNAMELEN) {
+
+ // Pull out fork lengths
+ data_size = READ_BE_UINT32(infoHeader + MBI_DFLEN);
+ rsrc_size = READ_BE_UINT32(infoHeader + MBI_RFLEN);
+
+ data_size_pad = (((data_size + 127) >> 7) << 7);
+ rsrc_size_pad = (((rsrc_size + 127) >> 7) << 7);
+
+ // Length check
+ int sumlen = MBI_INFOHDR + data_size_pad + rsrc_size_pad;
+
+ if (sumlen == filelen)
+ _resOffset = MBI_INFOHDR + data_size_pad;
+ }
+
+ if (_resOffset == -1) // MacBinary check is failed
+ _resOffset = 0; // Maybe we have dumped fork?
+
+ in.seek(_resOffset);
+
+ _dataOffset = in.readUint32BE() + _resOffset;
+ _mapOffset = in.readUint32BE() + _resOffset;
+ _dataLength = in.readUint32BE();
+ _mapLength = in.readUint32BE();
+
+ // do sanity check
+ if (_dataOffset >= filelen || _mapOffset >= filelen ||
+ _dataLength + _mapLength > filelen) {
+ _resOffset = -1;
+ return false;
+ }
+
+ debug(7, "got header: data %d [%d] map %d [%d]",
+ _dataOffset, _dataLength, _mapOffset, _mapLength);
+
+ readMap(in);
+
+ return true;
+}
+
+byte *MacResExtractor::getResource(Common::File in, const char *typeID, int16 resID, int *size) {
+ int i;
+ int typeNum = -1;
+ int resNum = -1;
+ byte *buf;
+ int len;
+
+ for (i = 0; i < _resMap.numTypes; i++)
+ if (strcmp(_resTypes[i].id, typeID) == 0) {
+ typeNum = i;
+ break;
+ }
+
+ if (typeNum == -1)
+ return NULL;
+
+ for (i = 0; i < _resTypes[typeNum].items; i++)
+ if (_resLists[typeNum][i].id == resID) {
+ resNum = i;
+ break;
+ }
+
+ if (resNum == -1)
+ return NULL;
+
+ in.seek(_dataOffset + _resLists[typeNum][resNum].dataOffset);
+
+ len = in.readUint32BE();
+ buf = (byte *)malloc(len);
+
+ in.read(buf, len);
+
+ *size = len;
+
+ return buf;
+}
+
+void MacResExtractor::readMap(Common::File in) {
+ int i, j, len;
+
+ in.seek(_mapOffset + 22);
+
+ _resMap.resAttr = in.readUint16BE();
+ _resMap.typeOffset = in.readUint16BE();
+ _resMap.nameOffset = in.readUint16BE();
+ _resMap.numTypes = in.readUint16BE();
+ _resMap.numTypes++;
+
+ in.seek(_mapOffset + _resMap.typeOffset + 2);
+ _resTypes = new ResType[_resMap.numTypes];
+
+ for (i = 0; i < _resMap.numTypes; i++) {
+ in.read(_resTypes[i].id, 4);
+ _resTypes[i].id[4] = 0;
+ _resTypes[i].items = in.readUint16BE();
+ _resTypes[i].offset = in.readUint16BE();
+ _resTypes[i].items++;
+ }
+
+ _resLists = new ResPtr[_resMap.numTypes];
+
+ for (i = 0; i < _resMap.numTypes; i++) {
+ _resLists[i] = new Resource[_resTypes[i].items];
+ in.seek(_resTypes[i].offset + _mapOffset + _resMap.typeOffset);
+
+ for (j = 0; j < _resTypes[i].items; j++) {
+ ResPtr resPtr = _resLists[i] + j;
+
+ resPtr->id = in.readUint16BE();
+ resPtr->nameOffset = in.readUint16BE();
+ resPtr->dataOffset = in.readUint32BE();
+ in.readUint32BE();
+ resPtr->name = 0;
+
+ resPtr->attr = resPtr->dataOffset >> 24;
+ resPtr->dataOffset &= 0xFFFFFF;
+ }
+
+ for (j = 0; j < _resTypes[i].items; j++) {
+ if (_resLists[i][j].nameOffset != -1) {
+ in.seek(_resLists[i][j].nameOffset + _mapOffset + _resMap.nameOffset);
+
+ len = in.readByte();
+ _resLists[i][j].name = new byte[len + 1];
+ _resLists[i][j].name[len] = 0;
+ in.read(_resLists[i][j].name, len);
+ }
+ }
+ }
+}
+
+int MacResExtractor::convertIcons(byte *data, int datasize, byte **cursor, int *w, int *h,
+ int *hotspot_x, int *hotspot_y, int *keycolor, byte **palette, int *palSize) {
+ Common::MemoryReadStream dis(data, datasize);
+ int i, b;
+ byte imageByte;
+ byte *iconData;
+ int numBytes;
+ int pixelsPerByte, bpp;
+ int ctSize;
+ byte bitmask;
+ int iconRowBytes, iconBounds[4];
+ int ignored;
+ int iconDataSize;
+
+ dis.readUint16BE(); // type
+ dis.readUint32BE(); // offset to pixel map
+ dis.readUint32BE(); // offset to pixel data
+ dis.readUint32BE(); // expanded cursor data
+ dis.readUint16BE(); // expanded data depth
+ dis.readUint32BE(); // reserved
+
+ // Grab B/W icon data
+ *cursor = (byte *)malloc(16 * 16);
+ for (i = 0; i < 32; i++) {
+ imageByte = dis.readByte();
+ for (b = 0; b < 8; b++)
+ cursor[0][i*8+b] = (byte)((imageByte &
+ (0x80 >> b)) > 0? 0x0F: 0x00);
+ }
+
+ // Apply mask data
+ for (i = 0; i < 32; i++) {
+ imageByte = dis.readByte();
+ for (b = 0; b < 8; b++)
+ if ((imageByte & (0x80 >> b)) == 0)
+ cursor[0][i*8+b] = 0xff;
+ }
+
+ *hotspot_y = dis.readUint16BE();
+ *hotspot_x = dis.readUint16BE();
+ *w = *h = 16;
+
+ // Use b/w cursor on backends which don't support cursor palettes
+ if (!_vm->_system->hasFeature(OSystem::kFeatureCursorHasPalette))
+ return 1;
+
+ dis.readUint32BE(); // reserved
+ dis.readUint32BE(); // cursorID
+
+ // Color version of cursor
+ dis.readUint32BE(); // baseAddr
+
+ // Keep only lowbyte for now
+ dis.readByte();
+ iconRowBytes = dis.readByte();
+
+ if (!iconRowBytes)
+ return 1;
+
+ iconBounds[0] = dis.readUint16BE();
+ iconBounds[1] = dis.readUint16BE();
+ iconBounds[2] = dis.readUint16BE();
+ iconBounds[3] = dis.readUint16BE();
+
+ dis.readUint16BE(); // pmVersion
+ dis.readUint16BE(); // packType
+ dis.readUint32BE(); // packSize
+
+ dis.readUint32BE(); // hRes
+ dis.readUint32BE(); // vRes
+
+ dis.readUint16BE(); // pixelType
+ dis.readUint16BE(); // pixelSize
+ dis.readUint16BE(); // cmpCount
+ dis.readUint16BE(); // cmpSize
+
+ dis.readUint32BE(); // planeByte
+ dis.readUint32BE(); // pmTable
+ dis.readUint32BE(); // reserved
+
+ // Pixel data for cursor
+ iconDataSize = iconRowBytes * (iconBounds[3] - iconBounds[1]);
+ iconData = (byte *)malloc(iconDataSize);
+ dis.read(iconData, iconDataSize);
+
+ // Color table
+ dis.readUint32BE(); // ctSeed
+ dis.readUint16BE(); // ctFlag
+ ctSize = dis.readUint16BE() + 1;
+
+ *palette = (byte *)malloc(ctSize * 4);
+
+ // Read just high byte of 16-bit color
+ for (int c = 0; c < ctSize; c++) {
+ // We just use indices 0..ctSize, so ignore color ID
+ dis.readUint16BE(); // colorID[c]
+
+ palette[0][c * 4 + 0] = dis.readByte();
+ ignored = dis.readByte();
+
+ palette[0][c * 4 + 1] = dis.readByte();
+ ignored = dis.readByte();
+
+ palette[0][c * 4 + 2] = dis.readByte();
+ ignored = dis.readByte();
+
+ palette[0][c * 4 + 3] = 0;
+ }
+
+ *palSize = ctSize;
+
+ numBytes =
+ (iconBounds[2] - iconBounds[0]) *
+ (iconBounds[3] - iconBounds[1]);
+
+ pixelsPerByte = (iconBounds[2] - iconBounds[0]) / iconRowBytes;
+ bpp = 8 / pixelsPerByte;
+
+ // build a mask to make sure the pixels are properly shifted out
+ bitmask = 0;
+ for (int m = 0; m < bpp; m++) {
+ bitmask <<= 1;
+ bitmask |= 1;
+ }
+
+ // Extract pixels from bytes
+ for (int j = 0; j < iconDataSize; j++)
+ for (b = 0; b < pixelsPerByte; b++) {
+ int idx = j * pixelsPerByte + (pixelsPerByte - 1 - b);
+
+ if (cursor[0][idx] != 0xff) // if mask is not there
+ cursor[0][idx] = (byte)((iconData[j] >> (b * bpp)) & bitmask);
+ }
+
+ free(iconData);
+
+ assert(datasize - dis.pos() == 0);
+
+ return 1;
+}
+
+
+
+void ScummEngine_v70he::readRoomsOffsets() {
+ int num, i;
+ byte *ptr;
+
+ debug(9, "readRoomOffsets()");
+
+ num = READ_LE_UINT16(_heV7RoomOffsets);
+ ptr = _heV7RoomOffsets + 2;
+ for (i = 0; i < num; i++) {
+ res.roomoffs[rtRoom][i] = READ_LE_UINT32(ptr);
+ ptr += 4;
+ }
+}
+
+void ScummEngine_v70he::readGlobalObjects() {
+ int num = _fileHandle->readUint16LE();
+ assert(num == _numGlobalObjects);
+
+ _fileHandle->read(_objectStateTable, num);
+ _fileHandle->read(_objectOwnerTable, num);
+ _fileHandle->read(_objectRoomTable, num);
+
+ _fileHandle->read(_classData, num * sizeof(uint32));
+
+#if defined(SCUMM_BIG_ENDIAN)
+ // Correct the endianess if necessary
+ for (int i = 0; i != num; i++)
+ _classData[i] = FROM_LE_32(_classData[i]);
+#endif
+}
+
+void ScummEngine_v99he::readMAXS(int blockSize) {
+ debug(0, "ScummEngine_v99he readMAXS: MAXS has blocksize %d", blockSize);
+
+ _numVariables = _fileHandle->readUint16LE();
+ _fileHandle->readUint16LE();
+ _numRoomVariables = _fileHandle->readUint16LE();
+ _numLocalObjects = _fileHandle->readUint16LE();
+ _numArray = _fileHandle->readUint16LE();
+ _fileHandle->readUint16LE();
+ _fileHandle->readUint16LE();
+ _numFlObject = _fileHandle->readUint16LE();
+ _numInventory = _fileHandle->readUint16LE();
+ _numRooms = _fileHandle->readUint16LE();
+ _numScripts = _fileHandle->readUint16LE();
+ _numSounds = _fileHandle->readUint16LE();
+ _numCharsets = _fileHandle->readUint16LE();
+ _numCostumes = _fileHandle->readUint16LE();
+ _numGlobalObjects = _fileHandle->readUint16LE();
+ _numImages = _fileHandle->readUint16LE();
+ _numSprites = _fileHandle->readUint16LE();
+ _numLocalScripts = _fileHandle->readUint16LE();
+ _HEHeapSize = _fileHandle->readUint16LE();
+ _numPalettes = _fileHandle->readUint16LE();
+ _numUnk = _fileHandle->readUint16LE();
+ _numTalkies = _fileHandle->readUint16LE();
+ _numNewNames = 10;
+
+ _objectRoomTable = (byte *)calloc(_numGlobalObjects, 1);
+ _numGlobalScripts = 2048;
+}
+
+void ScummEngine_v90he::readMAXS(int blockSize) {
+ debug(0, "ScummEngine_v90he readMAXS: MAXS has blocksize %d", blockSize);
+
+ _numVariables = _fileHandle->readUint16LE();
+ _fileHandle->readUint16LE();
+ _numRoomVariables = _fileHandle->readUint16LE();
+ _numLocalObjects = _fileHandle->readUint16LE();
+ _numArray = _fileHandle->readUint16LE();
+ _fileHandle->readUint16LE();
+ _fileHandle->readUint16LE();
+ _numFlObject = _fileHandle->readUint16LE();
+ _numInventory = _fileHandle->readUint16LE();
+ _numRooms = _fileHandle->readUint16LE();
+ _numScripts = _fileHandle->readUint16LE();
+ _numSounds = _fileHandle->readUint16LE();
+ _numCharsets = _fileHandle->readUint16LE();
+ _numCostumes = _fileHandle->readUint16LE();
+ _numGlobalObjects = _fileHandle->readUint16LE();
+ _numImages = _fileHandle->readUint16LE();
+ _numSprites = _fileHandle->readUint16LE();
+ _numLocalScripts = _fileHandle->readUint16LE();
+ _HEHeapSize = _fileHandle->readUint16LE();
+ _numNewNames = 10;
+
+ _objectRoomTable = (byte *)calloc(_numGlobalObjects, 1);
+ if (_features & GF_HE_985)
+ _numGlobalScripts = 2048;
+ else
+ _numGlobalScripts = 200;
+}
+
+void ScummEngine_v72he::readMAXS(int blockSize) {
+ debug(0, "ScummEngine_v72he readMAXS: MAXS has blocksize %d", blockSize);
+
+ _numVariables = _fileHandle->readUint16LE();
+ _fileHandle->readUint16LE();
+ _numBitVariables = _numRoomVariables = _fileHandle->readUint16LE();
+ _numLocalObjects = _fileHandle->readUint16LE();
+ _numArray = _fileHandle->readUint16LE();
+ _fileHandle->readUint16LE();
+ _numVerbs = _fileHandle->readUint16LE();
+ _numFlObject = _fileHandle->readUint16LE();
+ _numInventory = _fileHandle->readUint16LE();
+ _numRooms = _fileHandle->readUint16LE();
+ _numScripts = _fileHandle->readUint16LE();
+ _numSounds = _fileHandle->readUint16LE();
+ _numCharsets = _fileHandle->readUint16LE();
+ _numCostumes = _fileHandle->readUint16LE();
+ _numGlobalObjects = _fileHandle->readUint16LE();
+ _numImages = _fileHandle->readUint16LE();
+ _numNewNames = 10;
+
+ _objectRoomTable = (byte *)calloc(_numGlobalObjects, 1);
+ _numGlobalScripts = 200;
+}
+
+byte *ScummEngine_v72he::getStringAddress(int i) {
+ byte *addr = getResourceAddress(rtString, i);
+ if (addr == NULL)
+ return NULL;
+ return ((ScummEngine_v72he::ArrayHeader *)addr)->data;
+}
+
+int ScummEngine_v72he::getSoundResourceSize(int id) {
+ const byte *ptr;
+ int offs, size;
+
+ if (id > _numSounds) {
+ if (!_sound->getHEMusicDetails(id, offs, size)) {
+ debug(0, "getSoundResourceSize: musicID %d not found", id);
+ return 0;
+ }
+ } else {
+ ptr = getResourceAddress(rtSound, id);
+ if (!ptr)
+ return 0;
+
+ if (READ_UINT32(ptr) == MKID('RIFF')) {
+ byte flags;
+ int rate;
+
+ size = READ_BE_UINT32(ptr + 4);
+ Common::MemoryReadStream stream(ptr, size);
+
+ if (!loadWAVFromStream(stream, size, rate, flags)) {
+ error("getSoundResourceSize: Not a valid WAV file");
+ }
+ } else {
+ ptr += 8 + READ_BE_UINT32(ptr + 12);
+ if (READ_UINT32(ptr) == MKID('SBNG')) {
+ ptr += READ_BE_UINT32(ptr + 4);
+ }
+
+ assert(READ_UINT32(ptr) == MKID('SDAT'));
+ size = READ_BE_UINT32(ptr + 4) - 8;
+ }
+ }
+
+ return size;
+}
+
+void ScummEngine_v80he::createSound(int snd1id, int snd2id) {
+ debug(0, "createSound: snd1id %d snd2id %d", snd1id, snd2id);
+
+ byte *snd1Ptr, *snd2Ptr;
+ byte *sbng1Ptr, *sbng2Ptr;
+ byte *sdat1Ptr, *sdat2Ptr;
+ byte *src, *dst, *tmp;
+ int len, offs, size;
+ int sdat1size, sdat2size;
+
+ if (snd2id == -1) {
+ _sndPtrOffs = 0;
+ _sndTmrOffs = 0;
+ return;
+ }
+
+ if (snd1id != _curSndId) {
+ _curSndId = snd1id;
+ _sndPtrOffs = 0;
+ _sndTmrOffs = 0;
+ }
+
+ snd1Ptr = getResourceAddress(rtSound, snd1id);
+ assert(snd1Ptr);
+ snd2Ptr = getResourceAddress(rtSound, snd2id);
+ assert(snd2Ptr);
+
+ int i;
+ int chan = -1;
+ for (i = 0; i < ARRAYSIZE(_sound->_heChannel); i++) {
+ if (_sound->_heChannel[i].sound == snd1id)
+ chan = i;
+ }
+
+ sbng1Ptr = heFindResource(MKID('SBNG'), snd1Ptr);
+ sbng2Ptr = heFindResource(MKID('SBNG'), snd2Ptr);
+
+ if (sbng1Ptr != NULL && sbng2Ptr != NULL) {
+ if (chan != -1 && _sound->_heChannel[chan].codeOffs > 0) {
+ int curOffs = _sound->_heChannel[chan].codeOffs;
+
+ src = snd1Ptr + curOffs;
+ dst = sbng1Ptr + 8;
+ size = READ_BE_UINT32(sbng1Ptr + 4);
+ len = sbng1Ptr - snd1Ptr + size - curOffs;
+
+ byte *data = (byte *)malloc(len);
+ memcpy(data, src, len);
+ memcpy(dst, data, len);
+ free(data);
+
+ dst = sbng1Ptr + 8;
+ while ((size = READ_LE_UINT16(dst)) != 0)
+ dst += size;
+ } else {
+ dst = sbng1Ptr + 8;
+ }
+
+ _sound->_heChannel[chan].codeOffs = sbng1Ptr - snd1Ptr + 8;
+
+ tmp = sbng2Ptr + 8;
+ while ((offs = READ_LE_UINT16(tmp)) != 0) {
+ tmp += offs;
+ }
+
+ src = sbng2Ptr + 8;
+ len = tmp - sbng2Ptr - 6;
+ memcpy(dst, src, len);
+
+ int32 time;
+ while ((size = READ_LE_UINT16(dst)) != 0) {
+ time = READ_LE_UINT32(dst + 2);
+ time += _sndTmrOffs;
+ WRITE_LE_UINT32(dst + 2, time);
+ dst += size;
+ }
+ }
+
+ sdat1Ptr = heFindResource(MKID('SDAT'), snd1Ptr);
+ assert(sdat1Ptr);
+ sdat2Ptr = heFindResource(MKID('SDAT'), snd2Ptr);
+ assert(sdat2Ptr);
+
+ sdat1size = READ_BE_UINT32(sdat1Ptr + 4) - 8 - _sndPtrOffs;
+ sdat2size = READ_BE_UINT32(sdat2Ptr + 4) - 8;
+
+ debug(0, "SDAT size1 %d size2 %d", sdat1size, sdat2size);
+ if (sdat2size < sdat1size) {
+ src = sdat2Ptr + 8;
+ dst = sdat1Ptr + 8 + _sndPtrOffs;
+ len = sdat2size;
+
+ memcpy(dst, src, len);
+
+ _sndPtrOffs += sdat2size;
+ _sndTmrOffs += sdat2size;
+ } else {
+ src = sdat2Ptr + 8;
+ dst = sdat1Ptr + 8 + _sndPtrOffs;
+ len = sdat1size;
+
+ memcpy(dst, src, len);
+
+ if (sdat2size != sdat1size) {
+ src = sdat2Ptr + 8 + sdat1size;
+ dst = sdat1Ptr + 8;
+ len = sdat2size - sdat1size;
+
+ memcpy(dst, src, len);
+ }
+
+ _sndPtrOffs = sdat2size - sdat1size;
+ _sndTmrOffs += sdat2size;
+ }
+}
+
+} // End of namespace Scumm
Copied: scummvm/trunk/engines/scumm/he/resource_he.h (from rev 20696, scummvm/trunk/engines/scumm/he/resource_v7he.h)
===================================================================
--- scummvm/trunk/engines/scumm/he/resource_he.h (rev 0)
+++ scummvm/trunk/engines/scumm/he/resource_he.h 2006-02-15 18:48:49 UTC (rev 20703)
@@ -0,0 +1,556 @@
+/* ScummVM - Scumm Interpreter
+ * Copyright (C) 2004-2006 The ScummVM project
+ *
+ * Parts of code heavily based on:
+ * icoutils - A set of programs dealing with MS Windows icons and cursors.
+ * Copyright (C) 1998-2001 Oskar Liljeblad
+ *
+ * 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$
+ *
+ */
+
+#if !defined(RESOURCE_HE_H) && !defined(DISABLE_HE)
+#define RESOURCE_HE_H
+
+namespace Scumm {
+
+#define WINRES_ID_MAXLEN (256)
+
+/*
+ * Definitions
+ */
+
+#define ACTION_LIST 1 /* command: list resources */
+#define ACTION_EXTRACT 2 /* command: extract resources */
+#define CALLBACK_STOP 0 /* results of ResourceCallback */
+#define CALLBACK_CONTINUE 1
+#define CALLBACK_CONTINUE_RECURS 2
+
+#define MZ_HEADER(x) ((DOSImageHeader *)(x))
+#define NE_HEADER(x) ((OS2ImageHeader *)PE_HEADER(x))
+#define NE_TYPEINFO_NEXT(x) ((Win16NETypeInfo *)((byte *)(x) + sizeof(Win16NETypeInfo) + \
+ ((Win16NETypeInfo *)x)->count * sizeof(Win16NENameInfo)))
+#define NE_RESOURCE_NAME_IS_NUMERIC (0x8000)
+
+#define STRIP_RES_ID_FORMAT(x) (x != NULL && (x[0] == '-' || x[0] == '+') ? ++x : x)
+
+#define IMAGE_NUMBEROF_DIRECTORY_ENTRIES 16
+#define IMAGE_SIZEOF_SHORT_NAME 8
+
+#define IMAGE_RESOURCE_NAME_IS_STRING 0x80000000
+#define IMAGE_RESOURCE_DATA_IS_DIRECTORY 0x80000000
+
+#define PE_HEADER(module) \
+ ((Win32ImageNTHeaders*)((byte *)(module) + \
+ (((DOSImageHeader*)(module))->lfanew)))
+
+#define PE_SECTIONS(module) \
+ ((Win32ImageSectionHeader *)((byte *) &PE_HEADER(module)->optional_header + \
+ PE_HEADER(module)->file_header.size_of_optional_header))
+
+#define IMAGE_DOS_SIGNATURE 0x5A4D /* MZ */
+#define IMAGE_OS2_SIGNATURE 0x454E /* NE */
+#define IMAGE_OS2_SIGNATURE_LE 0x454C /* LE */
+#define IMAGE_OS2_SIGNATURE_LX 0x584C /* LX */
+#define IMAGE_VXD_SIGNATURE 0x454C /* LE */
+#define IMAGE_NT_SIGNATURE 0x00004550 /* PE00 */
+
+#if !defined (WIN32)
+#define IMAGE_SCN_CNT_CODE 0x00000020
+#define IMAGE_SCN_CNT_INITIALIZED_DATA 0x00000040
+#define IMAGE_SCN_CNT_UNINITIALIZED_DATA 0x00000080
+#endif
+
+#define IMAGE_DIRECTORY_ENTRY_EXPORT 0
+#define IMAGE_DIRECTORY_ENTRY_IMPORT 1
+#define IMAGE_DIRECTORY_ENTRY_RESOURCE 2
+#define IMAGE_DIRECTORY_ENTRY_EXCEPTION 3
+#define IMAGE_DIRECTORY_ENTRY_SECURITY 4
+#define IMAGE_DIRECTORY_ENTRY_BASERELOC 5
+#define IMAGE_DIRECTORY_ENTRY_DEBUG 6
+#define IMAGE_DIRECTORY_ENTRY_COPYRIGHT 7
+#define IMAGE_DIRECTORY_ENTRY_GLOBALPTR 8 /* (MIPS GP) */
+#define IMAGE_DIRECTORY_ENTRY_TLS 9
+#define IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG 10
+#define IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT 11
+#define IMAGE_DIRECTORY_ENTRY_IAT 12 /* Import Address Table */
+#define IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT 13
+#define IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR 14
+
+#if !defined (WIN32)
+#define RT_CURSOR 1
+#define RT_BITMAP 2
+#define RT_ICON 3
+#define RT_MENU 4
+#define RT_DIALOG 5
+#define RT_STRING 6
+#define RT_FONTDIR 7
+#define RT_FONT 8
+#define RT_ACCELERATOR 9
+#define RT_RCDATA 10
+#define RT_MESSAGELIST 11
+#define RT_GROUP_CURSOR 12
+#define RT_GROUP_ICON 14
+#endif
+
+#define RETURN_IF_BAD_POINTER(r, x) \
+ if (!check_offset(fi->memory, fi->total_size, fi->file->name(), &(x), sizeof(x))) \
+ return (r);
+#define RETURN_IF_BAD_OFFSET(r, x, s) \
+ if (!check_offset(fi->memory, fi->total_size, fi->file->name(), x, s)) \
+ return (r);
+
+class ScummEngine_v70he;
+
+class ResExtractor {
+public:
+ ResExtractor(ScummEngine_v70he *scumm);
+ virtual ~ResExtractor();
+
+ void setCursor(int id);
+
+ virtual int extractResource(int id, byte **buf) { return 0; };
+ virtual int convertIcons(byte *data, int datasize, byte **cursor, int *w, int *h,
+ int *hotspot_x, int *hotspot_y, int *keycolor,
+ byte **palette, int *palSize) { return 0; };
+
+ enum {
+ MAX_CACHED_CURSORS = 10
+ };
+
+ struct CachedCursor {
+ bool valid;
+ int id;
+ byte *bitmap;
+ int w, h;
+ int hotspot_x, hotspot_y;
+ uint32 last_used;
+ byte *palette;
+ int palSize;
+ };
+
+ ScummEngine_v70he *_vm;
+
+ ResExtractor::CachedCursor *findCachedCursor(int id);
+ ResExtractor::CachedCursor *getCachedCursorSlot();
+
+ bool _arg_raw;
+ char _fileName[256];
+ CachedCursor _cursorCache[MAX_CACHED_CURSORS];
+
+ typedef Common::MemoryReadStream MemoryReadStream;
+
+};
+
+class Win32ResExtractor : public ResExtractor {
+ public:
+ Win32ResExtractor(ScummEngine_v70he *scumm);
+ ~Win32ResExtractor() {};
+ int extractResource(int id, byte **data);
+ void setCursor(int id);
+ int convertIcons(byte *data, int datasize, byte **cursor, int *w, int *h,
+ int *hotspot_x, int *hotspot_y, int *keycolor, byte **palette, int *palSize);
+
+ private:
+ int extractResource_(const char *resType, char *resName, byte **data);
+/*
+ * Structures
+ */
+
+#if !defined(__GNUC__)
+ #pragma START_PACK_STRUCTS
+#endif
+
+ struct WinLibrary {
+ Common::File *file;
+ byte *memory;
+ byte *first_resource;
+ bool is_PE_binary;
+ int total_size;
+ };
+
+ struct WinResource {
+ char id[256];
+ void *this_;
+ void *children;
+ int level;
+ bool numeric_id;
+ bool is_directory;
+ };
+
+
+ struct Win32IconResDir {
+ byte width;
+ byte height;
+ byte color_count;
+ byte reserved;
+ };
+
+ struct Win32CursorDir {
+ uint16 width;
+ uint16 height;
+ };
+
+ struct Win32CursorIconDirEntry {
+ union {
+ Win32IconResDir icon;
+ Win32CursorDir cursor;
+ } res_info;
+ uint16 plane_count;
+ uint16 bit_count;
+ uint32 bytes_in_res;
+ uint16 res_id;
+ };
+
+ struct Win32CursorIconDir {
+ uint16 reserved;
+ uint16 type;
+ uint16 count;
+ Win32CursorIconDirEntry entries[1] GCC_PACK;
+ };
+
+ struct Win32CursorIconFileDirEntry {
+ byte width;
+ byte height;
+ byte color_count;
+ byte reserved;
+ uint16 hotspot_x;
+ uint16 hotspot_y;
+ uint32 dib_size;
+ uint32 dib_offset;
+ };
+
+ struct Win32CursorIconFileDir {
+ uint16 reserved;
+ uint16 type;
+ uint16 count;
+ Win32CursorIconFileDirEntry entries[1];
+ };
+
+ struct Win32BitmapInfoHeader {
+ uint32 size;
+ int32 width;
+ int32 height;
+ uint16 planes;
+ uint16 bit_count;
+ uint32 compression;
+ uint32 size_image;
+ int32 x_pels_per_meter;
+ int32 y_pels_per_meter;
+ uint32 clr_used;
+ uint32 clr_important;
+ };
+
+ struct Win32RGBQuad {
+ byte blue;
+ byte green;
+ byte red;
+ byte reserved;
+ };
+
+ struct Win32ImageResourceDirectoryEntry {
+ union {
+ struct {
+ #ifdef SCUMM_BIGENDIAN
+ unsigned name_is_string:1;
+ unsigned name_offset:31;
+ #else
+ unsigned name_offset:31;
+ unsigned name_is_string:1;
+ #endif
+ } s1;
+ uint32 name;
+ struct {
+ #ifdef SCUMM_BIG_ENDIAN
+ uint16 __pad;
+ uint16 id;
+ #else
+ uint16 id;
+ uint16 __pad;
+ #endif
+ } s2;
+ } u1;
+ union {
+ uint32 offset_to_data;
+ struct {
+ #ifdef SCUMM_BIG_ENDIAN
+ unsigned data_is_directory:1;
+ unsigned offset_to_directory:31;
+ #else
+ unsigned offset_to_directory:31;
+ unsigned data_is_directory:1;
+ #endif
+ } s;
+ } u2;
+ };
+
+ struct Win16NETypeInfo {
+ uint16 type_id;
+ uint16 count;
+ uint32 resloader; // FARPROC16 - smaller? uint16?
+ };
+
+ struct Win16NENameInfo {
+ uint16 offset;
+ uint16 length;
+ uint16 flags;
+ uint16 id;
+ uint16 handle;
+ uint16 usage;
+ };
+
+ struct OS2ImageHeader {
+ uint16 magic;
+ byte ver;
+ byte rev;
+ uint16 enttab;
+ uint16 cbenttab;
+ int32 crc;
+ uint16 flags;
+ uint16 autodata;
+ uint16 heap;
+ uint16 stack;
+ uint32 csip;
+ uint32 sssp;
+ uint16 cseg;
+ uint16 cmod;
+ uint16 cbnrestab;
+ uint16 segtab;
+ uint16 rsrctab;
+ uint16 restab;
+ uint16 modtab;
+ uint16 imptab;
+ uint32 nrestab;
+ uint16 cmovent;
+ uint16 align;
+ uint16 cres;
+ byte exetyp;
+ byte flagsothers;
+ uint16 fastload_offset;
+ uint16 fastload_length;
+ uint16 swaparea;
+ uint16 expver;
+ };
+
+ struct DOSImageHeader {
+ uint16 magic;
+ uint16 cblp;
+ uint16 cp;
+ uint16 crlc;
+ uint16 cparhdr;
+ uint16 minalloc;
+ uint16 maxalloc;
+ uint16 ss;
+ uint16 sp;
+ uint16 csum;
+ uint16 ip;
+ uint16 cs;
+ uint16 lfarlc;
+ uint16 ovno;
+ uint16 res[4];
+ uint16 oemid;
+ uint16 oeminfo;
+ uint16 res2[10];
+ uint32 lfanew;
+ };
+
+ struct Win32ImageFileHeader {
+ uint16 machine;
+ uint16 number_of_sections;
+ uint32 time_date_stamp;
+ uint32 pointer_to_symbol_table;
+ uint32 number_of_symbols;
+ uint16 size_of_optional_header;
+ uint16 characteristics;
+ };
+
+ struct Win32ImageDataDirectory {
+ uint32 virtual_address;
+ uint32 size;
+ };
+
+ struct Win32ImageOptionalHeader {
+ uint16 magic;
+ byte major_linker_version;
+ byte minor_linker_version;
+ uint32 size_of_code;
+ uint32 size_of_initialized_data;
+ uint32 size_of_uninitialized_data;
+ uint32 address_of_entry_point;
+ uint32 base_of_code;
+ uint32 base_of_data;
+ uint32 image_base;
+ uint32 section_alignment;
+ uint32 file_alignment;
+ uint16 major_operating_system_version;
+ uint16 minor_operating_system_version;
+ uint16 major_image_version;
+ uint16 minor_image_version;
+ uint16 major_subsystem_version;
+ uint16 minor_subsystem_version;
+ uint32 win32_version_value;
+ uint32 size_of_image;
+ uint32 size_of_headers;
+ uint32 checksum;
+ uint16 subsystem;
+ uint16 dll_characteristics;
+ uint32 size_of_stack_reserve;
+ uint32 size_of_stack_commit;
+ uint32 size_of_heap_reserve;
+ uint32 size_of_heap_commit;
+ uint32 loader_flags;
+ uint32 number_of_rva_and_sizes;
+ Win32ImageDataDirectory data_directory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES];
+ };
+
+ struct Win32ImageNTHeaders {
+ uint32 signature;
+ Win32ImageFileHeader file_header;
+ Win32ImageOptionalHeader optional_header;
+ };
+
+ struct Win32ImageSectionHeader {
+ byte name[IMAGE_SIZEOF_SHORT_NAME];
+ union {
+ uint32 physical_address;
+ uint32 virtual_size;
+ } misc;
+ uint32 virtual_address;
+ uint32 size_of_raw_data;
+ uint32 pointer_to_raw_data;
+ uint32 pointer_to_relocations;
+ uint32 pointer_to_linenumbers;
+ uint16 number_of_relocations;
+ uint16 number_of_linenumbers;
+ uint32 characteristics;
+ };
+
+ struct Win32ImageResourceDataEntry {
+ uint32 offset_to_data;
+ uint32 size;
+ uint32 code_page;
+ uint32 resource_handle;
+ };
+
+ struct Win32ImageResourceDirectory {
+ uint32 characteristics;
+ uint32 time_date_stamp;
+ uint16 major_version;
+ uint16 minor_version;
+ uint16 number_of_named_entries;
+ uint16 number_of_id_entries;
+ };
+
+#if !defined(__GNUC__)
+ #pragma END_PACK_STRUCTS
+#endif
+
+/*
+ * Function Prototypes
+ */
+
+ WinResource *list_resources(WinLibrary *, WinResource *, int *);
+ bool read_library(WinLibrary *);
+ WinResource *find_resource(WinLibrary *, const char *, const char *, const char *, int *);
+ byte *get_resource_entry(WinLibrary *, WinResource *, int *);
+ int do_resources(WinLibrary *, const char *, char *, char *, int, byte **);
+ bool compare_resource_id(WinResource *, const char *);
+ const char *res_type_string_to_id(const char *);
+
+ const char *res_type_id_to_string(int);
+ char *get_destination_name(WinLibrary *, char *, char *, char *);
+
+ byte *extract_resource(WinLibrary *, WinResource *, int *, bool *, char *, char *, bool);
+ int extract_resources(WinLibrary *, WinResource *, WinResource *, WinResource *, WinResource *, byte **);
+ byte *extract_group_icon_cursor_resource(WinLibrary *, WinResource *, char *, int *, bool);
+
+ bool decode_pe_resource_id(WinLibrary *, WinResource *, uint32);
+ bool decode_ne_resource_id(WinLibrary *, WinResource *, uint16);
+ WinResource *list_ne_type_resources(WinLibrary *, int *);
+ WinResource *list_ne_name_resources(WinLibrary *, WinResource *, int *);
+ WinResource *list_pe_resources(WinLibrary *, Win32ImageResourceDirectory *, int, int *);
+ int calc_vma_size(WinLibrary *);
+ int do_resources_recurs(WinLibrary *, WinResource *, WinResource *, WinResource *, WinResource *, const char *, char *, char *, int, byte **);
+ char *get_resource_id_quoted(WinResource *);
+ WinResource *find_with_resource_array(WinLibrary *, WinResource *, const char *);
+
+ bool check_offset(byte *, int, const char *, void *, int);
+
+ uint32 simple_vec(byte *data, uint32 ofs, byte size);
+
+ void fix_win32_cursor_icon_file_dir_endian(Win32CursorIconFileDir *obj);
+ void fix_win32_bitmap_info_header_endian(Win32BitmapInfoHeader *obj);
+ void fix_win32_cursor_icon_file_dir_entry_endian(Win32CursorIconFileDirEntry *obj);
+ void fix_win32_image_section_header(Win32ImageSectionHeader *obj);
+ void fix_os2_image_header_endian(OS2ImageHeader *obj);
+ void fix_win32_image_header_endian(Win32ImageNTHeaders *obj);
+ void fix_win32_image_data_directory(Win32ImageDataDirectory *obj);
+};
+
+class MacResExtractor : public ResExtractor {
+
+public:
+ MacResExtractor(ScummEngine_v70he *scumm);
+ ~MacResExtractor() { }
+ void setCursor(int id) ;
+
+private:
+ int extractResource(int id, byte **buf);
+ bool init(Common::File in);
+ void readMap(Common::File in);
+ byte *getResource(Common::File in, const char *typeID, int16 resID, int *size);
+ int convertIcons(byte *data, int datasize, byte **cursor, int *w, int *h,
+ int *hotspot_x, int *hotspot_y, int *keycolor, byte **palette, int *palSize);
+
+ struct ResMap {
+ int16 resAttr;
+ int16 typeOffset;
+ int16 nameOffset;
+ int16 numTypes;
+ };
+
+ struct ResType {
+ char id[5];
+ int16 items;
+ int16 offset;
+ };
+
+ struct Resource {
+ int16 id;
+ int16 nameOffset;
+ byte attr;
+ int32 dataOffset;
+ byte *name;
+ };
+
+ typedef Resource *ResPtr;
+
+private:
+ int _resOffset;
+ int32 _dataOffset;
+ int32 _dataLength;
+ int32 _mapOffset;
+ int32 _mapLength;
+ ResMap _resMap;
+ ResType *_resTypes;
+ ResPtr *_resLists;
+};
+
+} // End of namespace Scumm
+
+#endif
Deleted: scummvm/trunk/engines/scumm/he/resource_v7he.cpp
===================================================================
--- scummvm/trunk/engines/scumm/he/resource_v7he.cpp 2006-02-15 18:48:56 UTC (rev 20702)
+++ scummvm/trunk/engines/scumm/he/resource_v7he.cpp 2006-02-15 18:48:49 UTC (rev 20703)
@@ -1,1912 +0,0 @@
-/* ScummVM - Scumm Interpreter
- * Copyright (C) 2004-2006 The ScummVM project
- *
- * Parts of code heavily based on:
- * icoutils - A set of programs dealing with MS Windows icons and cursors.
- * Copyright (C) 1998-2001 Oskar Liljeblad
- *
- * 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/stdafx.h"
-#include "scumm/scumm.h"
-#include "scumm/he/intern_he.h"
-#include "scumm/resource.h"
-#include "scumm/he/resource_v7he.h"
-#include "scumm/sound.h"
-#include "scumm/util.h"
-#include "sound/wave.h"
-
-#include "common/stream.h"
-#include "common/system.h"
-
-namespace Scumm {
-
-ResExtractor::ResExtractor(ScummEngine_v70he *scumm)
- : _vm(scumm) {
-
- _fileName[0] = 0;
- memset(_cursorCache, 0, sizeof(_cursorCache));
-}
-
-ResExtractor::~ResExtractor() {
- for (int i = 0; i < MAX_CACHED_CURSORS; ++i) {
- CachedCursor *cc = &_cursorCache[i];
- if (cc->valid) {
- free(cc->bitmap);
- free(cc->palette);
- }
- }
- memset(_cursorCache, 0, sizeof(_cursorCache));
-}
-
-ResExtractor::CachedCursor *ResExtractor::findCachedCursor(int id) {
- for (int i = 0; i < MAX_CACHED_CURSORS; ++i) {
- CachedCursor *cc = &_cursorCache[i];
- if (cc->valid && cc->id == id) {
- return cc;
- }
- }
- return NULL;
-}
-
-ResExtractor::CachedCursor *ResExtractor::getCachedCursorSlot() {
- uint32 min_last_used = 0;
- CachedCursor *r = NULL;
- for (int i = 0; i < MAX_CACHED_CURSORS; ++i) {
- CachedCursor *cc = &_cursorCache[i];
- if (!cc->valid) {
- return cc;
- } else {
- if (min_last_used == 0 || cc->last_used < min_last_used) {
- min_last_used = cc->last_used;
- r = cc;
- }
- }
- }
- assert(r);
- free(r->bitmap);
- free(r->palette);
- memset(r, 0, sizeof(CachedCursor));
- return r;
-}
-
-void ResExtractor::setCursor(int id) {
- byte *cursorRes = 0;
- int cursorsize;
- int keycolor = 0;
- CachedCursor *cc = findCachedCursor(id);
- if (cc != NULL) {
- debug(7, "Found cursor %d in cache slot %d", id, cc - _cursorCache);
- } else {
- cc = getCachedCursorSlot();
- assert(cc && !cc->valid);
- cursorsize = extractResource(id, &cursorRes);
- convertIcons(cursorRes, cursorsize, &cc->bitmap, &cc->w, &cc->h, &cc->hotspot_x, &cc->hotspot_y, &keycolor, &cc->palette, &cc->palSize);
- debug(7, "Adding cursor %d to cache slot %d", id, cc - _cursorCache);
- free(cursorRes);
- cc->valid = true;
- cc->id = id;
- cc->last_used = g_system->getMillis();
- }
-
- if (_vm->_system->hasFeature(OSystem::kFeatureCursorHasPalette) && cc->palette)
- _vm->_system->setCursorPalette(cc->palette, 0, cc->palSize);
-
- _vm->setCursorHotspot(cc->hotspot_x, cc->hotspot_y);
- _vm->setCursorFromBuffer(cc->bitmap, cc->w, cc->h, cc->w);
-}
-
-
-/*
- * Static variables
- */
-const char *res_types[] = {
- /* 0x01: */
- "cursor", "bitmap", "icon", "menu", "dialog", "string",
- "fontdir", "font", "accelerator", "rcdata", "messagelist",
- "group_cursor", NULL, "group_icon", NULL,
- /* the following are not defined in winbase.h, but found in wrc. */
- /* 0x10: */
- "version", "dlginclude", NULL, "plugplay", "vxd",
- "anicursor", "aniicon"
-};
-#define RES_TYPE_COUNT (sizeof(res_types)/sizeof(char *))
-
-Win32ResExtractor::Win32ResExtractor(ScummEngine_v70he *scumm) : ResExtractor(scumm) {
-}
-
-int Win32ResExtractor::extractResource(int resId, byte **data) {
- char buf[20];
-
- snprintf(buf, sizeof(buf), "%d", resId);
-
- return extractResource_("group_cursor", buf, data);
-}
-
-int Win32ResExtractor::extractResource_(const char *resType, char *resName, byte **data) {
- char *arg_language = NULL;
- const char *arg_type = resType;
- char *arg_name = resName;
- int arg_action = ACTION_LIST;
- int ressize = 0;
-
- _arg_raw = false;
-
- /* translate --type option from resource type string to integer */
- arg_type = res_type_string_to_id(arg_type);
-
- WinLibrary fi;
-
- /* initiate stuff */
- fi.memory = NULL;
- fi.file = new Common::File;
-
- if (!_fileName[0]) { // We are running for the first time
- snprintf(_fileName, 256, "%s.he3", _vm->getBaseName());
-
- if (_vm->_substResFileNameIndex > 0) {
- char buf1[128];
-
- _vm->generateSubstResFileName(_fileName, buf1, sizeof(buf1));
- strcpy(_fileName, buf1);
- }
- }
-
-
- /* get file size */
- fi.file->open(_fileName);
- if (!fi.file->isOpen()) {
- error("Cannot open file %s", _fileName);
- }
-
- fi.total_size = fi.file->size();
- if (fi.total_size == -1) {
- error("Cannot get size of file %s", fi.file->name());
- goto cleanup;
- }
- if (fi.total_size == 0) {
- error("%s: file has a size of 0", fi.file->name());
- goto cleanup;
- }
-
- /* read all of file */
- fi.memory = (byte *)malloc(fi.total_size);
- if (fi.file->read(fi.memory, fi.total_size) == 0) {
- error("Cannot read from file %s", fi.file->name());
- goto cleanup;
- }
-
- /* identify file and find resource table */
- if (!read_library(&fi)) {
- /* error reported by read_library */
- goto cleanup;
- }
-
- // verbose_printf("file is a %s\n",
- // fi.is_PE_binary ? "Windows NT `PE' binary" : "Windows 3.1 `NE' binary");
-
- /* errors will be printed by the callback */
- ressize = do_resources(&fi, arg_type, arg_name, arg_language, arg_action, data);
-
- /* free stuff and close file */
- cleanup:
- if (fi.file != NULL)
- fi.file->close();
- if (fi.memory != NULL)
- free(fi.memory);
-
- return ressize;
-}
-
-
-/* res_type_id_to_string:
- * Translate a numeric resource type to it's corresponding string type.
- * (For informative-ness.)
- */
-const char *Win32ResExtractor::res_type_id_to_string(int id) {
- if (id == 241)
- return "toolbar";
- if (id > 0 && id <= (int)RES_TYPE_COUNT)
- return res_types[id-1];
- return NULL;
-}
-
-/* res_type_string_to_id:
- * Translate a resource type string to integer.
- * (Used to convert the --type option.)
- */
-const char *Win32ResExtractor::res_type_string_to_id(const char *type) {
- static const char *res_type_ids[] = {
- "-1", "-2", "-3", "-4", "-5", "-6", "-7", "-8", "-9", "-10",
- "-11", "-12", NULL, "-14", NULL, "-16", "-17", NULL, "-19",
- "-20", "-21", "-22"
- };
- int c;
-
- if (type == NULL)
- return NULL;
-
- for (c = 0 ; c < (int)RES_TYPE_COUNT ; c++) {
- if (res_types[c] != NULL && !scumm_stricmp(type, res_types[c]))
- return res_type_ids[c];
- }
-
- return type;
-}
-
-int Win32ResExtractor::extract_resources(WinLibrary *fi, WinResource *wr,
- WinResource *type_wr, WinResource *name_wr,
- WinResource *lang_wr, byte **data) {
- int size;
- bool free_it;
- const char *type;
- int32 id;
-
- if (*data) {
- error("Win32ResExtractor::extract_resources() more than one cursor");
- return 0;
- }
-
- *data = extract_resource(fi, wr, &size, &free_it, type_wr->id, (lang_wr == NULL ? NULL : lang_wr->id), _arg_raw);
-
- if (data == NULL) {
- error("Win32ResExtractor::extract_resources() problem with resource extraction");
- return 0;
- }
-
- /* get named resource type if possible */
- type = NULL;
- if ((id = strtol(type_wr->id, 0, 10)) != 0)
- type = res_type_id_to_string(id);
-
- debugC(DEBUG_RESOURCE, "extractCursor(). Found cursor name: %s%s%s [size=%d]",
- get_resource_id_quoted(name_wr),
- (lang_wr->id[0] != '\0' ? " language: " : ""),
- get_resource_id_quoted(lang_wr), size);
-
- return size;
-}
-
-/* extract_resource:
- * Extract a resource, returning pointer to data.
- */
-byte *Win32ResExtractor::extract_resource(WinLibrary *fi, WinResource *wr, int *size,
- bool *free_it, char *type, char *lang, bool raw) {
- char *str;
- int32 intval;
-
- /* just return pointer to data if raw */
- if (raw) {
- *free_it = false;
- /* get_resource_entry will print possible error */
- return get_resource_entry(fi, wr, size);
- }
-
- /* find out how to extract */
- str = type;
- if (str != NULL && (intval = strtol(STRIP_RES_ID_FORMAT(str), 0, 10))) {
- if (intval == (int)RT_GROUP_ICON) {
- *free_it = true;
- return extract_group_icon_cursor_resource(fi, wr, lang, size, true);
- }
- if (intval == (int)RT_GROUP_CURSOR) {
- *free_it = true;
- return extract_group_icon_cursor_resource(fi, wr, lang, size, false);
- }
- }
-
- return NULL;
-}
-
-/* extract_group_icon_resource:
- * Create a complete RT_GROUP_ICON resource, that can be written to
- * an `.ico' file without modifications. Returns an allocated
- * memory block that should be freed with free() once used.
- *
- * `root' is the offset in file that specifies the resource.
- * `base' is the offset that string pointers are calculated from.
- * `ressize' should point to an integer variable where the size of
- * the returned memory block will be placed.
- * `is_icon' indicates whether resource to be extracted is icon
- * or cursor group.
- */
-byte *Win32ResExtractor::extract_group_icon_cursor_resource(WinLibrary *fi, WinResource *wr, char *lang,
- int *ressize, bool is_icon) {
- Win32CursorIconDir *icondir;
- Win32CursorIconFileDir *fileicondir;
- byte *memory;
- int c, offset, skipped;
- int size;
-
- /* get resource data and size */
- icondir = (Win32CursorIconDir *)get_resource_entry(fi, wr, &size);
- if (icondir == NULL) {
- /* get_resource_entry will print error */
- return NULL;
- }
-
- /* calculate total size of output file */
- RETURN_IF_BAD_POINTER(NULL, icondir->count);
- skipped = 0;
- for (c = 0 ; c < icondir->count ; c++) {
- int level;
- int iconsize;
- char name[14];
- WinResource *fwr;
-
- RETURN_IF_BAD_POINTER(NULL, icondir->entries[c]);
- /*printf("%d. bytes_in_res=%d width=%d height=%d planes=%d bit_count=%d\n", c,
- icondir->entries[c].bytes_in_res,
- (is_icon ? icondir->entries[c].res_info.icon.width : icondir->entries[c].res_info.cursor.width),
- (is_icon ? icondir->entries[c].res_info.icon.height : icondir->entries[c].res_info.cursor.height),
- icondir->entries[c].plane_count,
- icondir->entries[c].bit_count);*/
-
- /* find the corresponding icon resource */
- snprintf(name, sizeof(name)/sizeof(char), "-%d", icondir->entries[c].res_id);
- fwr = find_resource(fi, (is_icon ? "-3" : "-1"), name, lang, &level);
- if (fwr == NULL) {
- error("%s: could not find `%s' in `%s' resource.",
- fi->file->name(), &name[1], (is_icon ? "group_icon" : "group_cursor"));
- return NULL;
- }
-
- if (get_resource_entry(fi, fwr, &iconsize) != NULL) {
- if (iconsize == 0) {
- debugC(DEBUG_RESOURCE, "%s: icon resource `%s' is empty, skipping", fi->file->name(), name);
- skipped++;
- continue;
- }
- if ((uint32)iconsize != icondir->entries[c].bytes_in_res) {
- debugC(DEBUG_RESOURCE, "%s: mismatch of size in icon resource `%s' and group (%d != %d)",
- fi->file->name(), name, iconsize, icondir->entries[c].bytes_in_res);
- }
- size += iconsize; /* size += icondir->entries[c].bytes_in_res; */
-
- /* cursor resources have two additional WORDs that contain
- * hotspot info */
- if (!is_icon)
- size -= sizeof(uint16)*2;
- }
- }
- offset = sizeof(Win32CursorIconFileDir) + (icondir->count-skipped) * sizeof(Win32CursorIconFileDirEntry);
- size += offset;
- *ressize = size;
-
- /* allocate that much memory */
- memory = (byte *)malloc(size);
- fileicondir = (Win32CursorIconFileDir *)memory;
-
- /* transfer Win32CursorIconDir structure members */
- fileicondir->reserved = icondir->reserved;
- fileicondir->type = icondir->type;
- fileicondir->count = icondir->count - skipped;
-
- /* transfer each cursor/icon: Win32CursorIconDirEntry and data */
- skipped = 0;
- for (c = 0 ; c < icondir->count ; c++) {
- int level;
- char name[14];
- WinResource *fwr;
- byte *data;
-
- /* find the corresponding icon resource */
- snprintf(name, sizeof(name)/sizeof(char), "-%d", icondir->entries[c].res_id);
- fwr = find_resource(fi, (is_icon ? "-3" : "-1"), name, lang, &level);
- if (fwr == NULL) {
- error("%s: could not find `%s' in `%s' resource.",
- fi->file->name(), &name[1], (is_icon ? "group_icon" : "group_cursor"));
- return NULL;
- }
-
- /* get data and size of that resource */
- data = (byte *)get_resource_entry(fi, fwr, &size);
- if (data == NULL) {
- /* get_resource_entry has printed error */
- return NULL;
- }
- if (size == 0) {
- skipped++;
- continue;
- }
-
- /* copy ICONDIRENTRY (not including last dwImageOffset) */
- memcpy(&fileicondir->entries[c-skipped], &icondir->entries[c],
- sizeof(Win32CursorIconFileDirEntry)-sizeof(uint32));
-
- /* special treatment for cursors */
- if (!is_icon) {
- fileicondir->entries[c-skipped].width = icondir->entries[c].res_info.cursor.width;
- fileicondir->entries[c-skipped].height = icondir->entries[c].res_info.cursor.height / 2;
- fileicondir->entries[c-skipped].color_count = 0;
- fileicondir->entries[c-skipped].reserved = 0;
- }
-
- /* set image offset and increase it */
- fileicondir->entries[c-skipped].dib_offset = offset;
-
- /* transfer resource into file memory */
- if (is_icon) {
- memcpy(&memory[offset], data, icondir->entries[c].bytes_in_res);
- } else {
- fileicondir->entries[c-skipped].hotspot_x = ((uint16 *) data)[0];
- fileicondir->entries[c-skipped].hotspot_y = ((uint16 *) data)[1];
- memcpy(&memory[offset], data+sizeof(uint16)*2,
- icondir->entries[c].bytes_in_res-sizeof(uint16)*2);
- offset -= sizeof(uint16)*2;
- }
-
- /* increase the offset pointer */
- offset += icondir->entries[c].bytes_in_res;
- }
-
- return memory;
-}
-
-/* check_offset:
- * Check if a chunk of data (determined by offset and size)
- * is within the bounds of the WinLibrary file.
- * Usually not called directly.
- */
-bool Win32ResExtractor::check_offset(byte *memory, int total_size, const char *name, void *offset, int size) {
- int need_size = (int)((byte *)offset - memory + size);
-
- debugC(DEBUG_RESOURCE, "check_offset: size=%x vs %x offset=%x size=%x",
- need_size, total_size, (byte *)offset - memory, size);
-
- if (need_size < 0 || need_size > total_size) {
- error("%s: premature end", name);
- return false;
- }
-
- return true;
-}
-
-
-/* do_resources:
- * Do something for each resource matching type, name and lang.
- */
-int Win32ResExtractor::do_resources(WinLibrary *fi, const char *type, char *name, char *lang, int action, byte **data) {
- WinResource *type_wr;
- WinResource *name_wr;
- WinResource *lang_wr;
- int size;
-
- type_wr = (WinResource *)calloc(sizeof(WinResource)*3, 1);
- name_wr = type_wr + 1;
- lang_wr = type_wr + 2;
-
- size = do_resources_recurs(fi, NULL, type_wr, name_wr, lang_wr, type, name, lang, action, data);
-
- free(type_wr);
-
- return size;
-}
-
-/* what is each entry in this directory level for? type, name or language? */
-#define WINRESOURCE_BY_LEVEL(x) ((x)==0 ? type_wr : ((x)==1 ? name_wr : lang_wr))
-
-/* does the id of this entry match the specified id? */
-#define LEVEL_MATCHES(x) (x == NULL || x ## _wr->id[0] == '\0' || compare_resource_id(x ## _wr, x))
-
-int Win32ResExtractor::do_resources_recurs(WinLibrary *fi, WinResource *base,
- WinResource *type_wr, WinResource *name_wr, WinResource *lang_wr,
- const char *type, char *name, char *lang, int action, byte **data) {
- int c, rescnt;
- WinResource *wr;
- uint32 size = 0;
-
- /* get a list of all resources at this level */
- wr = list_resources(fi, base, &rescnt);
- if (wr == NULL)
- if (size != 0)
- return size;
- else
- return 0;
-
- /* process each resource listed */
- for (c = 0 ; c < rescnt ; c++) {
- /* (over)write the corresponding WinResource holder with the current */
- memcpy(WINRESOURCE_BY_LEVEL(wr[c].level), wr+c, sizeof(WinResource));
-
- /* go deeper unless there is something that does NOT match */
- if (LEVEL_MATCHES(type) && LEVEL_MATCHES(name) && LEVEL_MATCHES(lang)) {
- if (wr->is_directory)
- size = do_resources_recurs(fi, wr+c, type_wr, name_wr, lang_wr, type, name, lang, action, data);
- else
- size = extract_resources(fi, wr+c, type_wr, name_wr, lang_wr, data);
- }
- }
-
- /* since we're moving back one level after this, unset the
- * WinResource holder used on this level */
- memset(WINRESOURCE_BY_LEVEL(wr[0].level), 0, sizeof(WinResource));
-
- return size;
-}
-
-/* return the resource id quoted if it's a string, otherwise just return it */
-char *Win32ResExtractor::get_resource_id_quoted(WinResource *wr) {
- static char tmp[WINRES_ID_MAXLEN+2];
-
- if (wr->numeric_id || wr->id[0] == '\0')
- return wr->id;
-
- sprintf(tmp, "'%s'", wr->id);
- return tmp;
-}
-
-bool Win32ResExtractor::compare_resource_id(WinResource *wr, const char *id) {
- if (wr->numeric_id) {
- int32 cmp1, cmp2;
- if (id[0] == '+')
- return false;
- if (id[0] == '-')
- id++;
- if (!(cmp1 = strtol(wr->id, 0, 10)) || !(cmp2 = strtol(id, 0, 10)) || cmp1 != cmp2)
- return false;
- } else {
- if (id[0] == '-')
- return false;
- if (id[0] == '+')
- id++;
- if (strcmp(wr->id, id))
- return false;
- }
-
- return true;
-}
-
-bool Win32ResExtractor::decode_pe_resource_id(WinLibrary *fi, WinResource *wr, uint32 value) {
- if (value & IMAGE_RESOURCE_NAME_IS_STRING) { /* numeric id */
- int c, len;
- uint16 *mem = (uint16 *)
- (fi->first_resource + (value & ~IMAGE_RESOURCE_NAME_IS_STRING));
-
- /* copy each char of the string, and terminate it */
- RETURN_IF_BAD_POINTER(false, *mem);
- len = mem[0];
- RETURN_IF_BAD_OFFSET(false, &mem[1], sizeof(uint16) * len);
-
- len = MIN(mem[0], (uint16)WINRES_ID_MAXLEN);
- for (c = 0 ; c < len ; c++)
- wr->id[c] = mem[c+1] & 0x00FF;
- wr->id[len] = '\0';
- } else { /* Unicode string id */
- /* translate id into a string */
- snprintf(wr->id, WINRES_ID_MAXLEN, "%d", value);
- }
-
- wr->numeric_id = (value & IMAGE_RESOURCE_NAME_IS_STRING ? false:true);
- return true;
-}
-
-byte *Win32ResExtractor::get_resource_entry(WinLibrary *fi, WinResource *wr, int *size) {
- if (fi->is_PE_binary) {
- Win32ImageResourceDataEntry *dataent;
-
- dataent = (Win32ImageResourceDataEntry *) wr->children;
- RETURN_IF_BAD_POINTER(NULL, *dataent);
- *size = dataent->size;
- RETURN_IF_BAD_OFFSET(NULL, fi->memory + dataent->offset_to_data, *size);
-
- return fi->memory + dataent->offset_to_data;
- } else {
- Win16NENameInfo *nameinfo;
- int sizeshift;
-
- nameinfo = (Win16NENameInfo *) wr->children;
- sizeshift = *((uint16 *) fi->first_resource - 1);
- *size = nameinfo->length << sizeshift;
- RETURN_IF_BAD_OFFSET(NULL, fi->memory + (nameinfo->offset << sizeshift), *size);
-
- return fi->memory + (nameinfo->offset << sizeshift);
- }
-}
-
-bool Win32ResExtractor::decode_ne_resource_id(WinLibrary *fi, WinResource *wr, uint16 value) {
- if (value & NE_RESOURCE_NAME_IS_NUMERIC) { /* numeric id */
- /* translate id into a string */
- snprintf(wr->id, WINRES_ID_MAXLEN, "%d", value & ~NE_RESOURCE_NAME_IS_NUMERIC);
- } else { /* ASCII string id */
- int len;
- char *mem = (char *)NE_HEADER(fi->memory)
- + NE_HEADER(fi->memory)->rsrctab
- + value;
-
- /* copy each char of the string, and terminate it */
- RETURN_IF_BAD_POINTER(false, *mem);
- len = mem[0];
- RETURN_IF_BAD_OFFSET(false, &mem[1], sizeof(char) * len);
- memcpy(wr->id, &mem[1], len);
- wr->id[len] = '\0';
- }
-
- wr->numeric_id = (value & NE_RESOURCE_NAME_IS_NUMERIC ? true:false);
- return true;
-}
-
-Win32ResExtractor::WinResource *Win32ResExtractor::list_pe_resources(WinLibrary *fi, Win32ImageResourceDirectory *pe_res, int level, int *count) {
- WinResource *wr;
- int c, rescnt;
- Win32ImageResourceDirectoryEntry *dirent
- = (Win32ImageResourceDirectoryEntry *)(pe_res + 1);
-
- /* count number of `type' resources */
- RETURN_IF_BAD_POINTER(NULL, *dirent);
- rescnt = pe_res->number_of_named_entries + pe_res->number_of_id_entries;
- *count = rescnt;
-
- /* allocate WinResource's */
- wr = (WinResource *)malloc(sizeof(WinResource) * rescnt);
-
- /* fill in the WinResource's */
- for (c = 0 ; c < rescnt ; c++) {
- RETURN_IF_BAD_POINTER(NULL, dirent[c]);
- wr[c].this_ = pe_res;
- wr[c].level = level;
- wr[c].is_directory = (dirent[c].u2.s.data_is_directory);
- wr[c].children = fi->first_resource + dirent[c].u2.s.offset_to_directory;
-
- /* fill in wr->id, wr->numeric_id */
- if (!decode_pe_resource_id (fi, wr + c, dirent[c].u1.name))
- return NULL;
- }
-
- return wr;
-}
-
-Win32ResExtractor::WinResource *Win32ResExtractor::list_ne_name_resources(WinLibrary *fi, WinResource *typeres, int *count) {
- int c, rescnt;
- WinResource *wr;
- Win16NETypeInfo *typeinfo = (Win16NETypeInfo *) typeres->this_;
- Win16NENameInfo *nameinfo = (Win16NENameInfo *) typeres->children;
-
- /* count number of `type' resources */
- RETURN_IF_BAD_POINTER(NULL, typeinfo->count);
- *count = rescnt = typeinfo->count;
-
- /* allocate WinResource's */
- wr = (WinResource *)malloc(sizeof(WinResource) * rescnt);
-
- /* fill in the WinResource's */
- for (c = 0 ; c < rescnt ; c++) {
- RETURN_IF_BAD_POINTER(NULL, nameinfo[c]);
- wr[c].this_ = nameinfo+c;
- wr[c].is_directory = false;
- wr[c].children = nameinfo+c;
- wr[c].level = 1;
-
- /* fill in wr->id, wr->numeric_id */
- if (!decode_ne_resource_id(fi, wr + c, (nameinfo+c)->id))
- return NULL;
- }
-
- return wr;
-}
-
-Win32ResExtractor::WinResource *Win32ResExtractor::list_ne_type_resources(WinLibrary *fi, int *count) {
- int c, rescnt;
- WinResource *wr;
- Win16NETypeInfo *typeinfo;
-
- /* count number of `type' resources */
- typeinfo = (Win16NETypeInfo *) fi->first_resource;
- RETURN_IF_BAD_POINTER(NULL, *typeinfo);
- for (rescnt = 0 ; typeinfo->type_id != 0 ; rescnt++) {
- typeinfo = NE_TYPEINFO_NEXT(typeinfo);
- RETURN_IF_BAD_POINTER(NULL, *typeinfo);
- }
- *count = rescnt;
-
- /* allocate WinResource's */
- wr = (WinResource *)malloc(sizeof(WinResource) * rescnt);
-
- /* fill in the WinResource's */
- typeinfo = (Win16NETypeInfo *) fi->first_resource;
- for (c = 0 ; c < rescnt ; c++) {
- wr[c].this_ = typeinfo;
- wr[c].is_directory = (typeinfo->count != 0);
- wr[c].children = typeinfo+1;
- wr[c].level = 0;
-
- /* fill in wr->id, wr->numeric_id */
- if (!decode_ne_resource_id(fi, wr + c, typeinfo->type_id))
- return NULL;
-
- typeinfo = NE_TYPEINFO_NEXT(typeinfo);
- }
-
- return wr;
-}
-
-/* list_resources:
- * Return an array of WinResource's in the current
- * resource level specified by res.
- */
-Win32ResExtractor::WinResource *Win32ResExtractor::list_resources(WinLibrary *fi, WinResource *res, int *count) {
- if (res != NULL && !res->is_directory)
- return NULL;
-
- if (fi->is_PE_binary) {
- return list_pe_resources(fi, (Win32ImageResourceDirectory *)
- (res == NULL ? fi->first_resource : res->children),
- (res == NULL ? 0 : res->level+1),
- count);
- } else {
- return (res == NULL
- ? list_ne_type_resources(fi, count)
- : list_ne_name_resources(fi, res, count));
- }
-}
-
-/* read_library:
- * Read header and get resource directory offset in a Windows library
- * (AKA module).
- *
- */
-bool Win32ResExtractor::read_library(WinLibrary *fi) {
- /* check for DOS header signature `MZ' */
- RETURN_IF_BAD_POINTER(false, MZ_HEADER(fi->memory)->magic);
- if (MZ_HEADER(fi->memory)->magic == IMAGE_DOS_SIGNATURE) {
- DOSImageHeader *mz_header = MZ_HEADER(fi->memory);
-
- RETURN_IF_BAD_POINTER(false, mz_header->lfanew);
- if (mz_header->lfanew < sizeof(DOSImageHeader)) {
- error("%s: not a Windows library", fi->file->name());
- return false;
- }
- }
-
- /* check for OS2 (Win16) header signature `NE' */
- RETURN_IF_BAD_POINTER(false, NE_HEADER(fi->memory)->magic);
- if (NE_HEADER(fi->memory)->magic == IMAGE_OS2_SIGNATURE) {
- OS2ImageHeader *header = NE_HEADER(fi->memory);
-
- RETURN_IF_BAD_POINTER(false, header->rsrctab);
- RETURN_IF_BAD_POINTER(false, header->restab);
- if (header->rsrctab >= header->restab) {
- error("%s: no resource directory found", fi->file->name());
- return false;
- }
-
- fi->is_PE_binary = false;
- fi->first_resource = (byte *) NE_HEADER(fi->memory)
- + header->rsrctab + sizeof(uint16);
- RETURN_IF_BAD_POINTER(false, *(Win16NETypeInfo *) fi->first_resource);
-
- return true;
- }
-
- /* check for NT header signature `PE' */
- RETURN_IF_BAD_POINTER(false, PE_HEADER(fi->memory)->signature);
- if (PE_HEADER(fi->memory)->signature == IMAGE_NT_SIGNATURE) {
- Win32ImageSectionHeader *pe_sec;
- Win32ImageDataDirectory *dir;
- Win32ImageNTHeaders *pe_header;
- int d;
-
- /* allocate new memory */
- fi->total_size = calc_vma_size(fi);
- if (fi->total_size == 0) {
- /* calc_vma_size has reported error */
- return false;
- }
- fi->memory = (byte *)realloc(fi->memory, fi->total_size);
-
- /* relocate memory, start from last section */
- pe_header = PE_HEADER(fi->memory);
- RETURN_IF_BAD_POINTER(false, pe_header->file_header.number_of_sections);
-
- /* we don't need to do OFFSET checking for the sections.
- * calc_vma_size has already done that */
- for (d = pe_header->file_header.number_of_sections - 1; d >= 0 ; d--) {
- pe_sec = PE_SECTIONS(fi->memory) + d;
-
- if (pe_sec->characteristics & IMAGE_SCN_CNT_UNINITIALIZED_DATA)
- continue;
-
- //if (pe_sec->virtual_address + pe_sec->size_of_raw_data > fi->total_size)
-
- RETURN_IF_BAD_OFFSET(0, fi->memory + pe_sec->virtual_address, pe_sec->size_of_raw_data);
- RETURN_IF_BAD_OFFSET(0, fi->memory + pe_sec->pointer_to_raw_data, pe_sec->size_of_raw_data);
- if (pe_sec->virtual_address != pe_sec->pointer_to_raw_data) {
- memmove(fi->memory + pe_sec->virtual_address,
- fi->memory + pe_sec->pointer_to_raw_data,
- pe_sec->size_of_raw_data);
- }
- }
-
- /* find resource directory */
- RETURN_IF_BAD_POINTER(false, pe_header->optional_header.data_directory[IMAGE_DIRECTORY_ENTRY_RESOURCE]);
- dir = pe_header->optional_header.data_directory + IMAGE_DIRECTORY_ENTRY_RESOURCE;
- if (dir->size == 0) {
- error("%s: file contains no resources", fi->file->name());
- return false;
- }
-
- fi->first_resource = fi->memory + dir->virtual_address;
- fi->is_PE_binary = true;
- return true;
- }
-
- /* other (unknown) header signature was found */
- error("%s: not a Windows library", fi->file->name());
- return false;
-}
-
-/* calc_vma_size:
- * Calculate the total amount of memory needed for a 32-bit Windows
- * module. Returns -1 if file was too small.
- */
-int Win32ResExtractor::calc_vma_size(WinLibrary *fi) {
- Win32ImageSectionHeader *seg;
- int c, segcount, size;
-
- size = 0;
- RETURN_IF_BAD_POINTER(-1, PE_HEADER(fi->memory)->file_header.number_of_sections);
- segcount = PE_HEADER(fi->memory)->file_header.number_of_sections;
-
- /* If there are no segments, just process file like it is.
- * This is (probably) not the right thing to do, but problems
- * will be delt with later anyway.
- */
- if (segcount == 0)
- return fi->total_size;
-
- seg = PE_SECTIONS(fi->memory);
- RETURN_IF_BAD_POINTER(-1, *seg);
- for (c = 0 ; c < segcount ; c++) {
- RETURN_IF_BAD_POINTER(0, *seg);
-
- size = MAX((uint32)size, seg->virtual_address + seg->size_of_raw_data);
- /* I have no idea what misc.virtual_size is for... */
- size = MAX((uint32)size, seg->virtual_address + seg->misc.virtual_size);
- seg++;
- }
-
- return size;
-}
-
-Win32ResExtractor::WinResource *Win32ResExtractor::find_with_resource_array(WinLibrary *fi, WinResource *wr, const char *id) {
- int c, rescnt;
- WinResource *return_wr;
-
- wr = list_resources(fi, wr, &rescnt);
- if (wr == NULL)
- return NULL;
-
- for (c = 0 ; c < rescnt ; c++) {
- if (compare_resource_id(&wr[c], id)) {
- /* duplicate WinResource and return it */
- return_wr = (WinResource *)malloc(sizeof(WinResource));
- memcpy(return_wr, &wr[c], sizeof(WinResource));
-
- /* free old WinResource */
- free(wr);
- return return_wr;
- }
- }
-
- return NULL;
-}
-
-Win32ResExtractor::WinResource *Win32ResExtractor::find_resource(WinLibrary *fi, const char *type, const char *name, const char *language, int *level) {
- WinResource *wr;
-
- *level = 0;
- if (type == NULL)
- return NULL;
- wr = find_with_resource_array(fi, NULL, type);
- if (wr == NULL || !wr->is_directory)
- return wr;
-
- *level = 1;
- if (name == NULL)
- return wr;
- wr = find_with_resource_array(fi, wr, name);
- if (wr == NULL || !wr->is_directory)
- return wr;
-
- *level = 2;
- if (language == NULL)
- return wr;
- wr = find_with_resource_array(fi, wr, language);
- return wr;
-}
-
-#define ROW_BYTES(bits) ((((bits) + 31) >> 5) << 2)
-
-
-int Win32ResExtractor::convertIcons(byte *data, int datasize, byte **cursor, int *w, int *h,
- int *hotspot_x, int *hotspot_y, int *keycolor, byte **pal, int *palSize) {
- Win32CursorIconFileDir dir;
- Win32CursorIconFileDirEntry *entries = NULL;
- uint32 offset;
- uint32 c, d;
- int completed;
- int matched = 0;
- MemoryReadStream *in = new MemoryReadStream(data, datasize);
-
- if (!in->read(&dir, sizeof(Win32CursorIconFileDir)- sizeof(Win32CursorIconFileDirEntry)))
- goto cleanup;
- fix_win32_cursor_icon_file_dir_endian(&dir);
-
- if (dir.reserved != 0) {
- error("not an icon or cursor file (reserved non-zero)");
- goto cleanup;
- }
- if (dir.type != 1 && dir.type != 2) {
- error("not an icon or cursor file (wrong type)");
- goto cleanup;
- }
-
- entries = (Win32CursorIconFileDirEntry *)malloc(dir.count * sizeof(Win32CursorIconFileDirEntry));
- for (c = 0; c < dir.count; c++) {
- if (!in->read(&entries[c], sizeof(Win32CursorIconFileDirEntry)))
- goto cleanup;
- fix_win32_cursor_icon_file_dir_entry_endian(&entries[c]);
- if (entries[c].reserved != 0)
- error("reserved is not zero");
- }
-
- offset = sizeof(Win32CursorIconFileDir) + (dir.count - 1) * (sizeof(Win32CursorIconFileDirEntry));
-
- for (completed = 0; completed < dir.count; ) {
- uint32 min_offset = 0x7fffffff;
- int previous = completed;
-
- for (c = 0; c < dir.count; c++) {
- if (entries[c].dib_offset == offset) {
- Win32BitmapInfoHeader bitmap;
- Win32RGBQuad *palette = NULL;
- uint32 palette_count = 0;
- uint32 image_size, mask_size;
- uint32 width, height;
- byte *image_data = NULL, *mask_data = NULL;
- byte *row = NULL;
-
- if (!in->read(&bitmap, sizeof(Win32BitmapInfoHeader)))
- goto local_cleanup;
-
- fix_win32_bitmap_info_header_endian(&bitmap);
- if (bitmap.size < sizeof(Win32BitmapInfoHeader)) {
- error("bitmap header is too short");
- goto local_cleanup;
- }
- if (bitmap.compression != 0) {
- error("compressed image data not supported");
- goto local_cleanup;
- }
- if (bitmap.x_pels_per_meter != 0)
- error("x_pels_per_meter field in bitmap should be zero");
- if (bitmap.y_pels_per_meter != 0)
- error("y_pels_per_meter field in bitmap should be zero");
- if (bitmap.clr_important != 0)
- error("clr_important field in bitmap should be zero");
- if (bitmap.planes != 1)
- error("planes field in bitmap should be one");
- if (bitmap.size != sizeof(Win32BitmapInfoHeader)) {
- uint32 skip = bitmap.size - sizeof(Win32BitmapInfoHeader);
- error("skipping %d bytes of extended bitmap header", skip);
- in->seek(skip, SEEK_CUR);
- }
- offset += bitmap.size;
-
- if (bitmap.clr_used != 0 || bitmap.bit_count < 24) {
- palette_count = (bitmap.clr_used != 0 ? bitmap.clr_used : 1 << bitmap.bit_count);
- palette = (Win32RGBQuad *)malloc(sizeof(Win32RGBQuad) * palette_count);
- if (!in->read(palette, sizeof(Win32RGBQuad) * palette_count))
- goto local_cleanup;
- offset += sizeof(Win32RGBQuad) * palette_count;
- }
-
- width = bitmap.width;
- height = ABS(bitmap.height)/2;
-
- image_size = height * ROW_BYTES(width * bitmap.bit_count);
- mask_size = height * ROW_BYTES(width);
-
- if (entries[c].dib_size != bitmap.size + image_size + mask_size + palette_count * sizeof(Win32RGBQuad))
- debugC(DEBUG_RESOURCE, "incorrect total size of bitmap (%d specified; %d real)",
- entries[c].dib_size,
- bitmap.size + image_size + mask_size + palette_count * sizeof(Win32RGBQuad)
- );
-
- image_data = (byte *)malloc(image_size);
- if (!in->read(image_data, image_size))
- goto local_cleanup;
-
- mask_data = (byte *)malloc(mask_size);
- if (!in->read(mask_data, mask_size))
- goto local_cleanup;
-
- offset += image_size;
- offset += mask_size;
- completed++;
- matched++;
-
- *hotspot_x = entries[c].hotspot_x;
- *hotspot_y = entries[c].hotspot_y;
- *w = width;
- *h = height;
- *keycolor = 0;
- *cursor = (byte *)malloc(width * height);
-
- row = (byte *)malloc(width * 4);
-
- for (d = 0; d < height; d++) {
- uint32 x;
- uint32 y = (bitmap.height < 0 ? d : height - d - 1);
- uint32 imod = y * (image_size / height) * 8 / bitmap.bit_count;
- //uint32 mmod = y * (mask_size / height) * 8;
-
- for (x = 0; x < width; x++) {
-
- uint32 color = simple_vec(image_data, x + imod, bitmap.bit_count);
-
- // FIXME?: This works only with b/w cursors and white index may be
- // different. But now it's enough.
- if (color) {
- cursor[0][width * d + x] = 15; // white in SCUMM
- } else {
- cursor[0][width * d + x] = 255; // transparent
- }
- /*
-
- if (bitmap.bit_count <= 16) {
- if (color >= palette_count) {
- error("color out of range in image data");
- goto local_cleanup;
- }
- row[4*x+0] = palette[color].red;
- row[4*x+1] = palette[color].green;
- row[4*x+2] = palette[color].blue;
-
- } else {
- row[4*x+0] = (color >> 16) & 0xFF;
- row[4*x+1] = (color >> 8) & 0xFF;
- row[4*x+2] = (color >> 0) & 0xFF;
- }
- if (bitmap.bit_count == 32)
- row[4*x+3] = (color >> 24) & 0xFF;
- else
- row[4*x+3] = simple_vec(mask_data, x + mmod, 1) ? 0 : 0xFF;
- */
- }
-
- }
-
- if (row != NULL)
- free(row);
- if (palette != NULL)
- free(palette);
- if (image_data != NULL) {
- free(image_data);
- free(mask_data);
- }
- continue;
-
- local_cleanup:
-
- if (row != NULL)
- free(row);
- if (palette != NULL)
- free(palette);
- if (image_data != NULL) {
- free(image_data);
- free(mask_data);
- }
- goto cleanup;
- } else {
- if (entries[c].dib_offset > offset)
- min_offset = MIN(min_offset, entries[c].dib_offset);
- }
- }
-
- if (previous == completed) {
- if (min_offset < offset) {
- error("offset of bitmap header incorrect (too low)");
- goto cleanup;
- }
- debugC(DEBUG_RESOURCE, "skipping %d bytes of garbage at %d", min_offset-offset, offset);
- in->seek(min_offset - offset, SEEK_CUR);
- offset = min_offset;
- }
- }
-
- free(entries);
- return matched;
-
-cleanup:
-
- free(entries);
- return -1;
-}
-
-uint32 Win32ResExtractor::simple_vec(byte *data, uint32 ofs, byte size) {
- switch (size) {
- case 1:
- return (data[ofs/8] >> (7 - ofs%8)) & 1;
- case 2:
- return (data[ofs/4] >> ((3 - ofs%4) << 1)) & 3;
- case 4:
- return (data[ofs/2] >> ((1 - ofs%2) << 2)) & 15;
- case 8:
- return data[ofs];
- case 16:
- return data[2*ofs] | data[2*ofs+1] << 8;
- case 24:
- return data[3*ofs] | data[3*ofs+1] << 8 | data[3*ofs+2] << 16;
- case 32:
- return data[4*ofs] | data[4*ofs+1] << 8 | data[4*ofs+2] << 16 | data[4*ofs+3] << 24;
- }
-
- return 0;
-}
-
-#define LE16(x) ((x) = TO_LE_16(x))
-#define LE32(x) ((x) = TO_LE_32(x))
-
-void Win32ResExtractor::fix_win32_cursor_icon_file_dir_endian(Win32CursorIconFileDir *obj) {
- LE16(obj->reserved);
- LE16(obj->type);
- LE16(obj->count);
-}
-
-void Win32ResExtractor::fix_win32_bitmap_info_header_endian(Win32BitmapInfoHeader *obj) {
- LE32(obj->size);
- LE32(obj->width);
- LE32(obj->height);
- LE16(obj->planes);
- LE16(obj->bit_count);
- LE32(obj->compression);
- LE32(obj->size_image);
- LE32(obj->x_pels_per_meter);
- LE32(obj->y_pels_per_meter);
- LE32(obj->clr_used);
- LE32(obj->clr_important);
-}
-
-void Win32ResExtractor::fix_win32_cursor_icon_file_dir_entry_endian(Win32CursorIconFileDirEntry *obj) {
- LE16(obj->hotspot_x);
- LE16(obj->hotspot_y);
- LE32(obj->dib_size);
- LE32(obj->dib_offset);
-}
-
-void Win32ResExtractor::fix_win32_image_section_header(Win32ImageSectionHeader *obj) {
- LE32(obj->misc.physical_address);
- LE32(obj->virtual_address);
- LE32(obj->size_of_raw_data);
- LE32(obj->pointer_to_raw_data);
- LE32(obj->pointer_to_relocations);
- LE32(obj->pointer_to_linenumbers);
- LE16(obj->number_of_relocations);
- LE16(obj->number_of_linenumbers);
- LE32(obj->characteristics);
-}
-
-void Win32ResExtractor::fix_os2_image_header_endian(OS2ImageHeader *obj) {
- LE16(obj->magic);
- LE16(obj->enttab);
- LE16(obj->cbenttab);
- LE32(obj->crc);
- LE16(obj->flags);
- LE16(obj->autodata);
- LE16(obj->heap);
- LE16(obj->stack);
- LE32(obj->csip);
- LE32(obj->sssp);
- LE16(obj->cseg);
- LE16(obj->cmod);
- LE16(obj->cbnrestab);
- LE16(obj->segtab);
- LE16(obj->rsrctab);
- LE16(obj->restab);
- LE16(obj->modtab);
- LE16(obj->imptab);
- LE32(obj->nrestab);
- LE16(obj->cmovent);
- LE16(obj->align);
- LE16(obj->cres);
- LE16(obj->fastload_offset);
- LE16(obj->fastload_length);
- LE16(obj->swaparea);
- LE16(obj->expver);
-}
-
-/* fix_win32_image_header_endian:
- * NOTE: This assumes that the optional header is always available.
- */
-void Win32ResExtractor::fix_win32_image_header_endian(Win32ImageNTHeaders *obj) {
- LE32(obj->signature);
- LE16(obj->file_header.machine);
- LE16(obj->file_header.number_of_sections);
- LE32(obj->file_header.time_date_stamp);
- LE32(obj->file_header.pointer_to_symbol_table);
- LE32(obj->file_header.number_of_symbols);
- LE16(obj->file_header.size_of_optional_header);
- LE16(obj->file_header.characteristics);
- LE16(obj->optional_header.magic);
- LE32(obj->optional_header.size_of_code);
- LE32(obj->optional_header.size_of_initialized_data);
- LE32(obj->optional_header.size_of_uninitialized_data);
- LE32(obj->optional_header.address_of_entry_point);
- LE32(obj->optional_header.base_of_code);
- LE32(obj->optional_header.base_of_data);
- LE32(obj->optional_header.image_base);
- LE32(obj->optional_header.section_alignment);
- LE32(obj->optional_header.file_alignment);
- LE16(obj->optional_header.major_operating_system_version);
- LE16(obj->optional_header.minor_operating_system_version);
- LE16(obj->optional_header.major_image_version);
- LE16(obj->optional_header.minor_image_version);
- LE16(obj->optional_header.major_subsystem_version);
- LE16(obj->optional_header.minor_subsystem_version);
- LE32(obj->optional_header.win32_version_value);
- LE32(obj->optional_header.size_of_image);
- LE32(obj->optional_header.size_of_headers);
- LE32(obj->optional_header.checksum);
- LE16(obj->optional_header.subsystem);
- LE16(obj->optional_header.dll_characteristics);
- LE32(obj->optional_header.size_of_stack_reserve);
- LE32(obj->optional_header.size_of_stack_commit);
- LE32(obj->optional_header.size_of_heap_reserve);
- LE32(obj->optional_header.size_of_heap_commit);
- LE32(obj->optional_header.loader_flags);
- LE32(obj->optional_header.number_of_rva_and_sizes);
-}
-
-void Win32ResExtractor::fix_win32_image_data_directory(Win32ImageDataDirectory *obj) {
- LE32(obj->virtual_address);
- LE32(obj->size);
-}
-
-
-MacResExtractor::MacResExtractor(ScummEngine_v70he *scumm) : ResExtractor(scumm) {
- _resOffset = -1;
-}
-
-int MacResExtractor::extractResource(int id, byte **buf) {
- Common::File in;
- int size;
-
- if (!_fileName[0]) // We are running for the first time
- if (_vm->_substResFileNameIndex > 0) {
- char buf1[128];
-
- snprintf(buf1, 128, "%s.he3", _vm->getBaseName());
- _vm->generateSubstResFileName(buf1, _fileName, sizeof(buf1));
-
- // Some programs write it as .bin. Try that too
- if (!in.exists(_fileName)) {
- strcpy(buf1, _fileName);
- snprintf(_fileName, 128, "%s.bin", buf1);
-
- if (!in.exists(_fileName)) {
- // And finally check if we have dumped resource fork
- snprintf(_fileName, 128, "%s.rsrc", buf1);
- if (!in.exists(_fileName)) {
- error("Cannot open file any of files '%s', '%s.bin', '%s.rsrc",
- buf1, buf1, buf1);
- }
- }
- }
- }
-
- in.open(_fileName);
- if (!in.isOpen()) {
- error("Cannot open file %s", _fileName);
- }
-
- // we haven't calculated it
- if (_resOffset == -1) {
- if (!init(in))
- error("Resource fork is missing in file '%s'", _fileName);
- in.close();
- in.open(_fileName);
- }
-
- *buf = getResource(in, "crsr", 1000 + id, &size);
-
- in.close();
-
- if (*buf == NULL)
- error("There is no cursor ID #%d", 1000 + id);
-
- return size;
-}
-
-#define MBI_INFOHDR 128
-#define MBI_ZERO1 0
-#define MBI_NAMELEN 1
-#define MBI_ZERO2 74
-#define MBI_ZERO3 82
-#define MBI_DFLEN 83
-#define MBI_RFLEN 87
-#define MAXNAMELEN 63
-
-bool MacResExtractor::init(Common::File in) {
- byte infoHeader[MBI_INFOHDR];
- int32 data_size, rsrc_size;
- int32 data_size_pad, rsrc_size_pad;
- int filelen;
-
- filelen = in.size();
- in.read(infoHeader, MBI_INFOHDR);
-
- // Maybe we have MacBinary?
- if (infoHeader[MBI_ZERO1] == 0 && infoHeader[MBI_ZERO2] == 0 &&
- infoHeader[MBI_ZERO3] == 0 && infoHeader[MBI_NAMELEN] <= MAXNAMELEN) {
-
- // Pull out fork lengths
- data_size = READ_BE_UINT32(infoHeader + MBI_DFLEN);
- rsrc_size = READ_BE_UINT32(infoHeader + MBI_RFLEN);
-
- data_size_pad = (((data_size + 127) >> 7) << 7);
- rsrc_size_pad = (((rsrc_size + 127) >> 7) << 7);
-
- // Length check
- int sumlen = MBI_INFOHDR + data_size_pad + rsrc_size_pad;
-
- if (sumlen == filelen)
- _resOffset = MBI_INFOHDR + data_size_pad;
- }
-
- if (_resOffset == -1) // MacBinary check is failed
- _resOffset = 0; // Maybe we have dumped fork?
-
- in.seek(_resOffset);
-
- _dataOffset = in.readUint32BE() + _resOffset;
- _mapOffset = in.readUint32BE() + _resOffset;
- _dataLength = in.readUint32BE();
- _mapLength = in.readUint32BE();
-
- // do sanity check
- if (_dataOffset >= filelen || _mapOffset >= filelen ||
- _dataLength + _mapLength > filelen) {
- _resOffset = -1;
- return false;
- }
-
- debug(7, "got header: data %d [%d] map %d [%d]",
- _dataOffset, _dataLength, _mapOffset, _mapLength);
-
- readMap(in);
-
- return true;
-}
-
-byte *MacResExtractor::getResource(Common::File in, const char *typeID, int16 resID, int *size) {
- int i;
- int typeNum = -1;
- int resNum = -1;
- byte *buf;
- int len;
-
- for (i = 0; i < _resMap.numTypes; i++)
- if (strcmp(_resTypes[i].id, typeID) == 0) {
- typeNum = i;
- break;
- }
-
- if (typeNum == -1)
- return NULL;
-
- for (i = 0; i < _resTypes[typeNum].items; i++)
- if (_resLists[typeNum][i].id == resID) {
- resNum = i;
- break;
- }
-
- if (resNum == -1)
- return NULL;
-
- in.seek(_dataOffset + _resLists[typeNum][resNum].dataOffset);
-
- len = in.readUint32BE();
- buf = (byte *)malloc(len);
-
- in.read(buf, len);
-
- *size = len;
-
- return buf;
-}
-
-void MacResExtractor::readMap(Common::File in) {
- int i, j, len;
-
- in.seek(_mapOffset + 22);
-
- _resMap.resAttr = in.readUint16BE();
- _resMap.typeOffset = in.readUint16BE();
- _resMap.nameOffset = in.readUint16BE();
- _resMap.numTypes = in.readUint16BE();
- _resMap.numTypes++;
-
- in.seek(_mapOffset + _resMap.typeOffset + 2);
- _resTypes = new ResType[_resMap.numTypes];
-
- for (i = 0; i < _resMap.numTypes; i++) {
- in.read(_resTypes[i].id, 4);
- _resTypes[i].id[4] = 0;
- _resTypes[i].items = in.readUint16BE();
- _resTypes[i].offset = in.readUint16BE();
- _resTypes[i].items++;
- }
-
- _resLists = new ResPtr[_resMap.numTypes];
-
- for (i = 0; i < _resMap.numTypes; i++) {
- _resLists[i] = new Resource[_resTypes[i].items];
- in.seek(_resTypes[i].offset + _mapOffset + _resMap.typeOffset);
-
- for (j = 0; j < _resTypes[i].items; j++) {
- ResPtr resPtr = _resLists[i] + j;
-
- resPtr->id = in.readUint16BE();
- resPtr->nameOffset = in.readUint16BE();
- resPtr->dataOffset = in.readUint32BE();
- in.readUint32BE();
- resPtr->name = 0;
-
- resPtr->attr = resPtr->dataOffset >> 24;
- resPtr->dataOffset &= 0xFFFFFF;
- }
-
- for (j = 0; j < _resTypes[i].items; j++) {
- if (_resLists[i][j].nameOffset != -1) {
- in.seek(_resLists[i][j].nameOffset + _mapOffset + _resMap.nameOffset);
-
- len = in.readByte();
- _resLists[i][j].name = new byte[len + 1];
- _resLists[i][j].name[len] = 0;
- in.read(_resLists[i][j].name, len);
- }
- }
- }
-}
-
-int MacResExtractor::convertIcons(byte *data, int datasize, byte **cursor, int *w, int *h,
- int *hotspot_x, int *hotspot_y, int *keycolor, byte **palette, int *palSize) {
- Common::MemoryReadStream dis(data, datasize);
- int i, b;
- byte imageByte;
- byte *iconData;
- int numBytes;
- int pixelsPerByte, bpp;
- int ctSize;
- byte bitmask;
- int iconRowBytes, iconBounds[4];
- int ignored;
- int iconDataSize;
-
- dis.readUint16BE(); // type
- dis.readUint32BE(); // offset to pixel map
- dis.readUint32BE(); // offset to pixel data
- dis.readUint32BE(); // expanded cursor data
- dis.readUint16BE(); // expanded data depth
- dis.readUint32BE(); // reserved
-
- // Grab B/W icon data
- *cursor = (byte *)malloc(16 * 16);
- for (i = 0; i < 32; i++) {
- imageByte = dis.readByte();
- for (b = 0; b < 8; b++)
- cursor[0][i*8+b] = (byte)((imageByte &
- (0x80 >> b)) > 0? 0x0F: 0x00);
- }
-
- // Apply mask data
- for (i = 0; i < 32; i++) {
- imageByte = dis.readByte();
- for (b = 0; b < 8; b++)
- if ((imageByte & (0x80 >> b)) == 0)
- cursor[0][i*8+b] = 0xff;
- }
-
- *hotspot_y = dis.readUint16BE();
- *hotspot_x = dis.readUint16BE();
- *w = *h = 16;
-
- // Use b/w cursor on backends which don't support cursor palettes
- if (!_vm->_system->hasFeature(OSystem::kFeatureCursorHasPalette))
- return 1;
-
- dis.readUint32BE(); // reserved
- dis.readUint32BE(); // cursorID
-
- // Color version of cursor
- dis.readUint32BE(); // baseAddr
-
- // Keep only lowbyte for now
- dis.readByte();
- iconRowBytes = dis.readByte();
-
- if (!iconRowBytes)
- return 1;
-
- iconBounds[0] = dis.readUint16BE();
- iconBounds[1] = dis.readUint16BE();
- iconBounds[2] = dis.readUint16BE();
- iconBounds[3] = dis.readUint16BE();
-
- dis.readUint16BE(); // pmVersion
- dis.readUint16BE(); // packType
- dis.readUint32BE(); // packSize
-
- dis.readUint32BE(); // hRes
- dis.readUint32BE(); // vRes
-
- dis.readUint16BE(); // pixelType
- dis.readUint16BE(); // pixelSize
- dis.readUint16BE(); // cmpCount
- dis.readUint16BE(); // cmpSize
-
- dis.readUint32BE(); // planeByte
- dis.readUint32BE(); // pmTable
- dis.readUint32BE(); // reserved
-
- // Pixel data for cursor
- iconDataSize = iconRowBytes * (iconBounds[3] - iconBounds[1]);
- iconData = (byte *)malloc(iconDataSize);
- dis.read(iconData, iconDataSize);
-
- // Color table
- dis.readUint32BE(); // ctSeed
- dis.readUint16BE(); // ctFlag
- ctSize = dis.readUint16BE() + 1;
-
- *palette = (byte *)malloc(ctSize * 4);
-
- // Read just high byte of 16-bit color
- for (int c = 0; c < ctSize; c++) {
- // We just use indices 0..ctSize, so ignore color ID
- dis.readUint16BE(); // colorID[c]
-
- palette[0][c * 4 + 0] = dis.readByte();
- ignored = dis.readByte();
-
- palette[0][c * 4 + 1] = dis.readByte();
- ignored = dis.readByte();
-
- palette[0][c * 4 + 2] = dis.readByte();
- ignored = dis.readByte();
-
- palette[0][c * 4 + 3] = 0;
- }
-
- *palSize = ctSize;
-
- numBytes =
- (iconBounds[2] - iconBounds[0]) *
- (iconBounds[3] - iconBounds[1]);
-
- pixelsPerByte = (iconBounds[2] - iconBounds[0]) / iconRowBytes;
- bpp = 8 / pixelsPerByte;
-
- // build a mask to make sure the pixels are properly shifted out
- bitmask = 0;
- for (int m = 0; m < bpp; m++) {
- bitmask <<= 1;
- bitmask |= 1;
- }
-
- // Extract pixels from bytes
- for (int j = 0; j < iconDataSize; j++)
- for (b = 0; b < pixelsPerByte; b++) {
- int idx = j * pixelsPerByte + (pixelsPerByte - 1 - b);
-
- if (cursor[0][idx] != 0xff) // if mask is not there
- cursor[0][idx] = (byte)((iconData[j] >> (b * bpp)) & bitmask);
- }
-
- free(iconData);
-
- assert(datasize - dis.pos() == 0);
-
- return 1;
-}
-
-
-
-void ScummEngine_v70he::readRoomsOffsets() {
- int num, i;
- byte *ptr;
-
- debug(9, "readRoomOffsets()");
-
- num = READ_LE_UINT16(_heV7RoomOffsets);
- ptr = _heV7RoomOffsets + 2;
- for (i = 0; i < num; i++) {
- res.roomoffs[rtRoom][i] = READ_LE_UINT32(ptr);
- ptr += 4;
- }
-}
-
-void ScummEngine_v70he::readGlobalObjects() {
- int num = _fileHandle->readUint16LE();
- assert(num == _numGlobalObjects);
-
- _fileHandle->read(_objectStateTable, num);
- _fileHandle->read(_objectOwnerTable, num);
- _fileHandle->read(_objectRoomTable, num);
-
- _fileHandle->read(_classData, num * sizeof(uint32));
-
-#if defined(SCUMM_BIG_ENDIAN)
- // Correct the endianess if necessary
- for (int i = 0; i != num; i++)
- _classData[i] = FROM_LE_32(_classData[i]);
-#endif
-}
-
-void ScummEngine_v99he::readMAXS(int blockSize) {
- debug(0, "ScummEngine_v99he readMAXS: MAXS has blocksize %d", blockSize);
-
- _numVariables = _fileHandle->readUint16LE();
- _fileHandle->readUint16LE();
- _numRoomVariables = _fileHandle->readUint16LE();
- _numLocalObjects = _fileHandle->readUint16LE();
- _numArray = _fileHandle->readUint16LE();
- _fileHandle->readUint16LE();
- _fileHandle->readUint16LE();
- _numFlObject = _fileHandle->readUint16LE();
- _numInventory = _fileHandle->readUint16LE();
- _numRooms = _fileHandle->readUint16LE();
- _numScripts = _fileHandle->readUint16LE();
- _numSounds = _fileHandle->readUint16LE();
- _numCharsets = _fileHandle->readUint16LE();
- _numCostumes = _fileHandle->readUint16LE();
- _numGlobalObjects = _fileHandle->readUint16LE();
- _numImages = _fileHandle->readUint16LE();
- _numSprites = _fileHandle->readUint16LE();
- _numLocalScripts = _fileHandle->readUint16LE();
- _HEHeapSize = _fileHandle->readUint16LE();
- _numPalettes = _fileHandle->readUint16LE();
- _numUnk = _fileHandle->readUint16LE();
- _numTalkies = _fileHandle->readUint16LE();
- _numNewNames = 10;
-
- _objectRoomTable = (byte *)calloc(_numGlobalObjects, 1);
- _numGlobalScripts = 2048;
-}
-
-void ScummEngine_v90he::readMAXS(int blockSize) {
- debug(0, "ScummEngine_v90he readMAXS: MAXS has blocksize %d", blockSize);
-
- _numVariables = _fileHandle->readUint16LE();
- _fileHandle->readUint16LE();
- _numRoomVariables = _fileHandle->readUint16LE();
- _numLocalObjects = _fileHandle->readUint16LE();
- _numArray = _fileHandle->readUint16LE();
- _fileHandle->readUint16LE();
- _fileHandle->readUint16LE();
- _numFlObject = _fileHandle->readUint16LE();
- _numInventory = _fileHandle->readUint16LE();
- _numRooms = _fileHandle->readUint16LE();
- _numScripts = _fileHandle->readUint16LE();
- _numSounds = _fileHandle->readUint16LE();
- _numCharsets = _fileHandle->readUint16LE();
- _numCostumes = _fileHandle->readUint16LE();
- _numGlobalObjects = _fileHandle->readUint16LE();
- _numImages = _fileHandle->readUint16LE();
- _numSprites = _fileHandle->readUint16LE();
- _numLocalScripts = _fileHandle->readUint16LE();
- _HEHeapSize = _fileHandle->readUint16LE();
- _numNewNames = 10;
-
- _objectRoomTable = (byte *)calloc(_numGlobalObjects, 1);
- if (_features & GF_HE_985)
- _numGlobalScripts = 2048;
- else
- _numGlobalScripts = 200;
-}
-
-void ScummEngine_v72he::readMAXS(int blockSize) {
- debug(0, "ScummEngine_v72he readMAXS: MAXS has blocksize %d", blockSize);
-
- _numVariables = _fileHandle->readUint16LE();
- _fileHandle->readUint16LE();
- _numBitVariables = _numRoomVariables = _fileHandle->readUint16LE();
- _numLocalObjects = _fileHandle->readUint16LE();
- _numArray = _fileHandle->readUint16LE();
- _fileHandle->readUint16LE();
- _numVerbs = _fileHandle->readUint16LE();
- _numFlObject = _fileHandle->readUint16LE();
- _numInventory = _fileHandle->readUint16LE();
- _numRooms = _fileHandle->readUint16LE();
- _numScripts = _fileHandle->readUint16LE();
- _numSounds = _fileHandle->readUint16LE();
- _numCharsets = _fileHandle->readUint16LE();
- _numCostumes = _fileHandle->readUint16LE();
- _numGlobalObjects = _fileHandle->readUint16LE();
- _numImages = _fileHandle->readUint16LE();
- _numNewNames = 10;
-
- _objectRoomTable = (byte *)calloc(_numGlobalObjects, 1);
- _numGlobalScripts = 200;
-}
-
-byte *ScummEngine_v72he::getStringAddress(int i) {
- byte *addr = getResourceAddress(rtString, i);
- if (addr == NULL)
- return NULL;
- return ((ScummEngine_v72he::ArrayHeader *)addr)->data;
-}
-
-int ScummEngine_v72he::getSoundResourceSize(int id) {
- const byte *ptr;
- int offs, size;
-
- if (id > _numSounds) {
- if (!_sound->getHEMusicDetails(id, offs, size)) {
- debug(0, "getSoundResourceSize: musicID %d not found", id);
- return 0;
- }
- } else {
- ptr = getResourceAddress(rtSound, id);
- if (!ptr)
- return 0;
-
- if (READ_UINT32(ptr) == MKID('RIFF')) {
- byte flags;
- int rate;
-
- size = READ_BE_UINT32(ptr + 4);
- Common::MemoryReadStream stream(ptr, size);
-
- if (!loadWAVFromStream(stream, size, rate, flags)) {
- error("getSoundResourceSize: Not a valid WAV file");
- }
- } else {
- ptr += 8 + READ_BE_UINT32(ptr + 12);
- if (READ_UINT32(ptr) == MKID('SBNG')) {
- ptr += READ_BE_UINT32(ptr + 4);
- }
-
- assert(READ_UINT32(ptr) == MKID('SDAT'));
- size = READ_BE_UINT32(ptr + 4) - 8;
- }
- }
-
- return size;
-}
-
-void ScummEngine_v80he::createSound(int snd1id, int snd2id) {
- debug(0, "createSound: snd1id %d snd2id %d", snd1id, snd2id);
-
- byte *snd1Ptr, *snd2Ptr;
- byte *sbng1Ptr, *sbng2Ptr;
- byte *sdat1Ptr, *sdat2Ptr;
- byte *src, *dst, *tmp;
- int len, offs, size;
- int sdat1size, sdat2size;
-
- if (snd2id == -1) {
- _sndPtrOffs = 0;
- _sndTmrOffs = 0;
- return;
- }
-
- if (snd1id != _curSndId) {
- _curSndId = snd1id;
- _sndPtrOffs = 0;
- _sndTmrOffs = 0;
- }
-
- snd1Ptr = getResourceAddress(rtSound, snd1id);
- assert(snd1Ptr);
- snd2Ptr = getResourceAddress(rtSound, snd2id);
- assert(snd2Ptr);
-
- int i;
- int chan = -1;
- for (i = 0; i < ARRAYSIZE(_sound->_heChannel); i++) {
- if (_sound->_heChannel[i].sound == snd1id)
- chan = i;
- }
-
- sbng1Ptr = heFindResource(MKID('SBNG'), snd1Ptr);
- sbng2Ptr = heFindResource(MKID('SBNG'), snd2Ptr);
-
- if (sbng1Ptr != NULL && sbng2Ptr != NULL) {
- if (chan != -1 && _sound->_heChannel[chan].codeOffs > 0) {
- int curOffs = _sound->_heChannel[chan].codeOffs;
-
- src = snd1Ptr + curOffs;
- dst = sbng1Ptr + 8;
- size = READ_BE_UINT32(sbng1Ptr + 4);
- len = sbng1Ptr - snd1Ptr + size - curOffs;
-
- byte *data = (byte *)malloc(len);
- memcpy(data, src, len);
- memcpy(dst, data, len);
- free(data);
-
- dst = sbng1Ptr + 8;
- while ((size = READ_LE_UINT16(dst)) != 0)
- dst += size;
- } else {
- dst = sbng1Ptr + 8;
- }
-
- _sound->_heChannel[chan].codeOffs = sbng1Ptr - snd1Ptr + 8;
-
- tmp = sbng2Ptr + 8;
- while ((offs = READ_LE_UINT16(tmp)) != 0) {
- tmp += offs;
- }
-
- src = sbng2Ptr + 8;
- len = tmp - sbng2Ptr - 6;
- memcpy(dst, src, len);
-
- int32 time;
- while ((size = READ_LE_UINT16(dst)) != 0) {
- time = READ_LE_UINT32(dst + 2);
- time += _sndTmrOffs;
- WRITE_LE_UINT32(dst + 2, time);
- dst += size;
- }
- }
-
- sdat1Ptr = heFindResource(MKID('SDAT'), snd1Ptr);
- assert(sdat1Ptr);
- sdat2Ptr = heFindResource(MKID('SDAT'), snd2Ptr);
- assert(sdat2Ptr);
-
- sdat1size = READ_BE_UINT32(sdat1Ptr + 4) - 8 - _sndPtrOffs;
- sdat2size = READ_BE_UINT32(sdat2Ptr + 4) - 8;
-
- debug(0, "SDAT size1 %d size2 %d", sdat1size, sdat2size);
- if (sdat2size < sdat1size) {
- src = sdat2Ptr + 8;
- dst = sdat1Ptr + 8 + _sndPtrOffs;
- len = sdat2size;
-
- memcpy(dst, src, len);
-
- _sndPtrOffs += sdat2size;
- _sndTmrOffs += sdat2size;
- } else {
- src = sdat2Ptr + 8;
- dst = sdat1Ptr + 8 + _sndPtrOffs;
- len = sdat1size;
-
- memcpy(dst, src, len);
-
- if (sdat2size != sdat1size) {
- src = sdat2Ptr + 8 + sdat1size;
- dst = sdat1Ptr + 8;
- len = sdat2size - sdat1size;
-
- memcpy(dst, src, len);
- }
-
- _sndPtrOffs = sdat2size - sdat1size;
- _sndTmrOffs += sdat2size;
- }
-}
-
-} // End of namespace Scumm
Deleted: scummvm/trunk/engines/scumm/he/resource_v7he.h
===================================================================
--- scummvm/trunk/engines/scumm/he/resource_v7he.h 2006-02-15 18:48:56 UTC (rev 20702)
+++ scummvm/trunk/engines/scumm/he/resource_v7he.h 2006-02-15 18:48:49 UTC (rev 20703)
@@ -1,556 +0,0 @@
-/* ScummVM - Scumm Interpreter
- * Copyright (C) 2004-2006 The ScummVM project
- *
- * Parts of code heavily based on:
- * icoutils - A set of programs dealing with MS Windows icons and cursors.
- * Copyright (C) 1998-2001 Oskar Liljeblad
- *
- * 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$
- *
- */
-
-#if !defined(RESOURCE_V7HE_H) && !defined(DISABLE_HE)
-#define RESOURCE_V7HE_H
-
-namespace Scumm {
-
-#define WINRES_ID_MAXLEN (256)
-
-/*
- * Definitions
- */
-
-#define ACTION_LIST 1 /* command: list resources */
-#define ACTION_EXTRACT 2 /* command: extract resources */
-#define CALLBACK_STOP 0 /* results of ResourceCallback */
-#define CALLBACK_CONTINUE 1
-#define CALLBACK_CONTINUE_RECURS 2
-
-#define MZ_HEADER(x) ((DOSImageHeader *)(x))
-#define NE_HEADER(x) ((OS2ImageHeader *)PE_HEADER(x))
-#define NE_TYPEINFO_NEXT(x) ((Win16NETypeInfo *)((byte *)(x) + sizeof(Win16NETypeInfo) + \
- ((Win16NETypeInfo *)x)->count * sizeof(Win16NENameInfo)))
-#define NE_RESOURCE_NAME_IS_NUMERIC (0x8000)
-
-#define STRIP_RES_ID_FORMAT(x) (x != NULL && (x[0] == '-' || x[0] == '+') ? ++x : x)
-
-#define IMAGE_NUMBEROF_DIRECTORY_ENTRIES 16
-#define IMAGE_SIZEOF_SHORT_NAME 8
-
-#define IMAGE_RESOURCE_NAME_IS_STRING 0x80000000
-#define IMAGE_RESOURCE_DATA_IS_DIRECTORY 0x80000000
-
-#define PE_HEADER(module) \
- ((Win32ImageNTHeaders*)((byte *)(module) + \
- (((DOSImageHeader*)(module))->lfanew)))
-
-#define PE_SECTIONS(module) \
- ((Win32ImageSectionHeader *)((byte *) &PE_HEADER(module)->optional_header + \
- PE_HEADER(module)->file_header.size_of_optional_header))
-
-#define IMAGE_DOS_SIGNATURE 0x5A4D /* MZ */
-#define IMAGE_OS2_SIGNATURE 0x454E /* NE */
-#define IMAGE_OS2_SIGNATURE_LE 0x454C /* LE */
-#define IMAGE_OS2_SIGNATURE_LX 0x584C /* LX */
-#define IMAGE_VXD_SIGNATURE 0x454C /* LE */
-#define IMAGE_NT_SIGNATURE 0x00004550 /* PE00 */
-
-#if !defined (WIN32)
-#define IMAGE_SCN_CNT_CODE 0x00000020
-#define IMAGE_SCN_CNT_INITIALIZED_DATA 0x00000040
-#define IMAGE_SCN_CNT_UNINITIALIZED_DATA 0x00000080
-#endif
-
-#define IMAGE_DIRECTORY_ENTRY_EXPORT 0
-#define IMAGE_DIRECTORY_ENTRY_IMPORT 1
-#define IMAGE_DIRECTORY_ENTRY_RESOURCE 2
-#define IMAGE_DIRECTORY_ENTRY_EXCEPTION 3
-#define IMAGE_DIRECTORY_ENTRY_SECURITY 4
-#define IMAGE_DIRECTORY_ENTRY_BASERELOC 5
-#define IMAGE_DIRECTORY_ENTRY_DEBUG 6
-#define IMAGE_DIRECTORY_ENTRY_COPYRIGHT 7
-#define IMAGE_DIRECTORY_ENTRY_GLOBALPTR 8 /* (MIPS GP) */
-#define IMAGE_DIRECTORY_ENTRY_TLS 9
-#define IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG 10
-#define IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT 11
-#define IMAGE_DIRECTORY_ENTRY_IAT 12 /* Import Address Table */
-#define IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT 13
-#define IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR 14
-
-#if !defined (WIN32)
-#define RT_CURSOR 1
-#define RT_BITMAP 2
-#define RT_ICON 3
-#define RT_MENU 4
-#define RT_DIALOG 5
-#define RT_STRING 6
-#define RT_FONTDIR 7
-#define RT_FONT 8
-#define RT_ACCELERATOR 9
-#define RT_RCDATA 10
-#define RT_MESSAGELIST 11
-#define RT_GROUP_CURSOR 12
-#define RT_GROUP_ICON 14
-#endif
-
-#define RETURN_IF_BAD_POINTER(r, x) \
- if (!check_offset(fi->memory, fi->total_size, fi->file->name(), &(x), sizeof(x))) \
- return (r);
-#define RETURN_IF_BAD_OFFSET(r, x, s) \
- if (!check_offset(fi->memory, fi->total_size, fi->file->name(), x, s)) \
- return (r);
-
-class ScummEngine_v70he;
-
-class ResExtractor {
-public:
- ResExtractor(ScummEngine_v70he *scumm);
- virtual ~ResExtractor();
-
- void setCursor(int id);
-
- virtual int extractResource(int id, byte **buf) { return 0; };
- virtual int convertIcons(byte *data, int datasize, byte **cursor, int *w, int *h,
- int *hotspot_x, int *hotspot_y, int *keycolor,
- byte **palette, int *palSize) { return 0; };
-
- enum {
- MAX_CACHED_CURSORS = 10
- };
-
- struct CachedCursor {
- bool valid;
- int id;
- byte *bitmap;
- int w, h;
- int hotspot_x, hotspot_y;
- uint32 last_used;
- byte *palette;
- int palSize;
- };
-
- ScummEngine_v70he *_vm;
-
- ResExtractor::CachedCursor *findCachedCursor(int id);
- ResExtractor::CachedCursor *getCachedCursorSlot();
-
- bool _arg_raw;
- char _fileName[256];
- CachedCursor _cursorCache[MAX_CACHED_CURSORS];
-
- typedef Common::MemoryReadStream MemoryReadStream;
-
-};
-
-class Win32ResExtractor : public ResExtractor {
- public:
- Win32ResExtractor(ScummEngine_v70he *scumm);
- ~Win32ResExtractor() {};
- int extractResource(int id, byte **data);
- void setCursor(int id);
- int convertIcons(byte *data, int datasize, byte **cursor, int *w, int *h,
- int *hotspot_x, int *hotspot_y, int *keycolor, byte **palette, int *palSize);
-
- private:
- int extractResource_(const char *resType, char *resName, byte **data);
-/*
- * Structures
- */
-
-#if !defined(__GNUC__)
- #pragma START_PACK_STRUCTS
-#endif
-
- struct WinLibrary {
- Common::File *file;
- byte *memory;
- byte *first_resource;
- bool is_PE_binary;
- int total_size;
- };
-
- struct WinResource {
- char id[256];
- void *this_;
- void *children;
- int level;
- bool numeric_id;
- bool is_directory;
- };
-
-
- struct Win32IconResDir {
- byte width;
- byte height;
- byte color_count;
- byte reserved;
- };
-
- struct Win32CursorDir {
- uint16 width;
- uint16 height;
- };
-
- struct Win32CursorIconDirEntry {
- union {
- Win32IconResDir icon;
- Win32CursorDir cursor;
- } res_info;
- uint16 plane_count;
- uint16 bit_count;
- uint32 bytes_in_res;
- uint16 res_id;
- };
-
- struct Win32CursorIconDir {
- uint16 reserved;
- uint16 type;
- uint16 count;
- Win32CursorIconDirEntry entries[1] GCC_PACK;
- };
-
- struct Win32CursorIconFileDirEntry {
- byte width;
- byte height;
- byte color_count;
- byte reserved;
- uint16 hotspot_x;
- uint16 hotspot_y;
- uint32 dib_size;
- uint32 dib_offset;
- };
-
- struct Win32CursorIconFileDir {
- uint16 reserved;
- uint16 type;
- uint16 count;
- Win32CursorIconFileDirEntry entries[1];
- };
-
- struct Win32BitmapInfoHeader {
- uint32 size;
- int32 width;
- int32 height;
- uint16 planes;
- uint16 bit_count;
- uint32 compression;
- uint32 size_image;
- int32 x_pels_per_meter;
- int32 y_pels_per_meter;
- uint32 clr_used;
- uint32 clr_important;
- };
-
- struct Win32RGBQuad {
- byte blue;
- byte green;
- byte red;
- byte reserved;
- };
-
- struct Win32ImageResourceDirectoryEntry {
- union {
- struct {
- #ifdef SCUMM_BIGENDIAN
- unsigned name_is_string:1;
- unsigned name_offset:31;
- #else
- unsigned name_offset:31;
- unsigned name_is_string:1;
- #endif
- } s1;
- uint32 name;
- struct {
- #ifdef SCUMM_BIG_ENDIAN
- uint16 __pad;
- uint16 id;
- #else
- uint16 id;
- uint16 __pad;
- #endif
- } s2;
- } u1;
- union {
- uint32 offset_to_data;
- struct {
- #ifdef SCUMM_BIG_ENDIAN
- unsigned data_is_directory:1;
- unsigned offset_to_directory:31;
- #else
- unsigned offset_to_directory:31;
- unsigned data_is_directory:1;
- #endif
- } s;
- } u2;
- };
-
- struct Win16NETypeInfo {
- uint16 type_id;
- uint16 count;
- uint32 resloader; // FARPROC16 - smaller? uint16?
- };
-
- struct Win16NENameInfo {
- uint16 offset;
- uint16 length;
- uint16 flags;
- uint16 id;
- uint16 handle;
- uint16 usage;
- };
-
- struct OS2ImageHeader {
- uint16 magic;
- byte ver;
- byte rev;
- uint16 enttab;
- uint16 cbenttab;
- int32 crc;
- uint16 flags;
- uint16 autodata;
- uint16 heap;
- uint16 stack;
- uint32 csip;
- uint32 sssp;
- uint16 cseg;
- uint16 cmod;
- uint16 cbnrestab;
- uint16 segtab;
- uint16 rsrctab;
- uint16 restab;
- uint16 modtab;
- uint16 imptab;
- uint32 nrestab;
- uint16 cmovent;
- uint16 align;
- uint16 cres;
- byte exetyp;
- byte flagsothers;
- uint16 fastload_offset;
- uint16 fastload_length;
- uint16 swaparea;
- uint16 expver;
- };
-
- struct DOSImageHeader {
- uint16 magic;
- uint16 cblp;
- uint16 cp;
- uint16 crlc;
- uint16 cparhdr;
- uint16 minalloc;
- uint16 maxalloc;
- uint16 ss;
- uint16 sp;
- uint16 csum;
- uint16 ip;
- uint16 cs;
- uint16 lfarlc;
- uint16 ovno;
- uint16 res[4];
- uint16 oemid;
- uint16 oeminfo;
- uint16 res2[10];
- uint32 lfanew;
- };
-
- struct Win32ImageFileHeader {
- uint16 machine;
- uint16 number_of_sections;
- uint32 time_date_stamp;
- uint32 pointer_to_symbol_table;
- uint32 number_of_symbols;
- uint16 size_of_optional_header;
- uint16 characteristics;
- };
-
- struct Win32ImageDataDirectory {
- uint32 virtual_address;
- uint32 size;
- };
-
- struct Win32ImageOptionalHeader {
- uint16 magic;
- byte major_linker_version;
- byte minor_linker_version;
- uint32 size_of_code;
- uint32 size_of_initialized_data;
- uint32 size_of_uninitialized_data;
- uint32 address_of_entry_point;
- uint32 base_of_code;
- uint32 base_of_data;
- uint32 image_base;
- uint32 section_alignment;
- uint32 file_alignment;
- uint16 major_operating_system_version;
- uint16 minor_operating_system_version;
- uint16 major_image_version;
- uint16 minor_image_version;
- uint16 major_subsystem_version;
- uint16 minor_subsystem_version;
- uint32 win32_version_value;
- uint32 size_of_image;
- uint32 size_of_headers;
- uint32 checksum;
- uint16 subsystem;
- uint16 dll_characteristics;
- uint32 size_of_stack_reserve;
- uint32 size_of_stack_commit;
- uint32 size_of_heap_reserve;
- uint32 size_of_heap_commit;
- uint32 loader_flags;
- uint32 number_of_rva_and_sizes;
- Win32ImageDataDirectory data_directory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES];
- };
-
- struct Win32ImageNTHeaders {
- uint32 signature;
- Win32ImageFileHeader file_header;
- Win32ImageOptionalHeader optional_header;
- };
-
- struct Win32ImageSectionHeader {
- byte name[IMAGE_SIZEOF_SHORT_NAME];
- union {
- uint32 physical_address;
- uint32 virtual_size;
- } misc;
- uint32 virtual_address;
- uint32 size_of_raw_data;
- uint32 pointer_to_raw_data;
- uint32 pointer_to_relocations;
- uint32 pointer_to_linenumbers;
- uint16 number_of_relocations;
- uint16 number_of_linenumbers;
- uint32 characteristics;
- };
-
- struct Win32ImageResourceDataEntry {
- uint32 offset_to_data;
- uint32 size;
- uint32 code_page;
- uint32 resource_handle;
- };
-
- struct Win32ImageResourceDirectory {
- uint32 characteristics;
- uint32 time_date_stamp;
- uint16 major_version;
- uint16 minor_version;
- uint16 number_of_named_entries;
- uint16 number_of_id_entries;
- };
-
-#if !defined(__GNUC__)
- #pragma END_PACK_STRUCTS
-#endif
-
-/*
- * Function Prototypes
- */
-
- WinResource *list_resources(WinLibrary *, WinResource *, int *);
- bool read_library(WinLibrary *);
- WinResource *find_resource(WinLibrary *, const char *, const char *, const char *, int *);
- byte *get_resource_entry(WinLibrary *, WinResource *, int *);
- int do_resources(WinLibrary *, const char *, char *, char *, int, byte **);
- bool compare_resource_id(WinResource *, const char *);
- const char *res_type_string_to_id(const char *);
-
- const char *res_type_id_to_string(int);
- char *get_destination_name(WinLibrary *, char *, char *, char *);
-
- byte *extract_resource(WinLibrary *, WinResource *, int *, bool *, char *, char *, bool);
- int extract_resources(WinLibrary *, WinResource *, WinResource *, WinResource *, WinResource *, byte **);
- byte *extract_group_icon_cursor_resource(WinLibrary *, WinResource *, char *, int *, bool);
-
- bool decode_pe_resource_id(WinLibrary *, WinResource *, uint32);
- bool decode_ne_resource_id(WinLibrary *, WinResource *, uint16);
- WinResource *list_ne_type_resources(WinLibrary *, int *);
- WinResource *list_ne_name_resources(WinLibrary *, WinResource *, int *);
- WinResource *list_pe_resources(WinLibrary *, Win32ImageResourceDirectory *, int, int *);
- int calc_vma_size(WinLibrary *);
- int do_resources_recurs(WinLibrary *, WinResource *, WinResource *, WinResource *, WinResource *, const char *, char *, char *, int, byte **);
- char *get_resource_id_quoted(WinResource *);
- WinResource *find_with_resource_array(WinLibrary *, WinResource *, const char *);
-
- bool check_offset(byte *, int, const char *, void *, int);
-
- uint32 simple_vec(byte *data, uint32 ofs, byte size);
-
- void fix_win32_cursor_icon_file_dir_endian(Win32CursorIconFileDir *obj);
- void fix_win32_bitmap_info_header_endian(Win32BitmapInfoHeader *obj);
- void fix_win32_cursor_icon_file_dir_entry_endian(Win32CursorIconFileDirEntry *obj);
- void fix_win32_image_section_header(Win32ImageSectionHeader *obj);
- void fix_os2_image_header_endian(OS2ImageHeader *obj);
- void fix_win32_image_header_endian(Win32ImageNTHeaders *obj);
- void fix_win32_image_data_directory(Win32ImageDataDirectory *obj);
-};
-
-class MacResExtractor : public ResExtractor {
-
-public:
- MacResExtractor(ScummEngine_v70he *scumm);
- ~MacResExtractor() { }
- void setCursor(int id) ;
-
-private:
- int extractResource(int id, byte **buf);
- bool init(Common::File in);
- void readMap(Common::File in);
- byte *getResource(Common::File in, const char *typeID, int16 resID, int *size);
- int convertIcons(byte *data, int datasize, byte **cursor, int *w, int *h,
- int *hotspot_x, int *hotspot_y, int *keycolor, byte **palette, int *palSize);
-
- struct ResMap {
- int16 resAttr;
- int16 typeOffset;
- int16 nameOffset;
- int16 numTypes;
- };
-
- struct ResType {
- char id[5];
- int16 items;
- int16 offset;
- };
-
- struct Resource {
- int16 id;
- int16 nameOffset;
- byte attr;
- int32 dataOffset;
- byte *name;
- };
-
- typedef Resource *ResPtr;
-
-private:
- int _resOffset;
- int32 _dataOffset;
- int32 _dataLength;
- int32 _mapOffset;
- int32 _mapLength;
- ResMap _resMap;
- ResType *_resTypes;
- ResPtr *_resLists;
-};
-
-} // End of namespace Scumm
-
-#endif
Modified: scummvm/trunk/engines/scumm/he/script_v100he.cpp
===================================================================
--- scummvm/trunk/engines/scumm/he/script_v100he.cpp 2006-02-15 18:48:56 UTC (rev 20702)
+++ scummvm/trunk/engines/scumm/he/script_v100he.cpp 2006-02-15 18:48:49 UTC (rev 20703)
@@ -30,7 +30,7 @@
#include "scumm/he/intern_he.h"
#include "scumm/object.h"
#include "scumm/resource.h"
-#include "scumm/he/resource_v7he.h"
+#include "scumm/he/resource_he.h"
#include "scumm/scumm.h"
#include "scumm/sound.h"
#include "scumm/he/sprite_he.h"
Copied: scummvm/trunk/engines/scumm/he/script_v60he.cpp (from rev 20696, scummvm/trunk/engines/scumm/he/script_v6he.cpp)
===================================================================
--- scummvm/trunk/engines/scumm/he/script_v60he.cpp (rev 0)
+++ scummvm/trunk/engines/scumm/he/script_v60he.cpp 2006-02-15 18:48:49 UTC (rev 20703)
@@ -0,0 +1,1276 @@
+/* ScummVM - Scumm Interpreter
+ * Copyright (C) 2001 Ludvig Strigeus
+ * Copyright (C) 2001-2006 The ScummVM project
+ *
+ * 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/stdafx.h"
+#include "common/savefile.h"
+
+#include "scumm/actor.h"
+#include "scumm/charset.h"
+#include "scumm/imuse.h"
+#include "scumm/he/intern_he.h"
+#include "scumm/object.h"
+#include "scumm/resource.h"
+#include "scumm/scumm.h"
+#include "scumm/sound.h"
+#include "scumm/usage_bits.h"
+#include "scumm/util.h"
+#include "scumm/verbs.h"
+
+namespace Scumm {
+
+struct vsUnpackCtx {
+ uint8 size;
+ uint8 type;
+ uint8 b;
+ uint8 *ptr;
+};
+
+struct vsPackCtx {
+ int size;
+ uint8 buf[256];
+};
+
+static void virtScreenSavePackBuf(vsPackCtx *ctx, uint8 *&dst, int len);
+static void virtScreenSavePackByte(vsPackCtx *ctx, uint8 *&dst, int len, uint8 b);
+static uint8 virtScreenLoadUnpack(vsUnpackCtx *ctx, byte *data);
+static int virtScreenSavePack(byte *dst, byte *src, int len, int unk);
+
+// Compatibility notes:
+//
+// FBEAR (fbear, fbeardemo)
+// transparency in akos.cpp
+// negative size in file read/write
+
+#define OPCODE(x) _OPCODE(ScummEngine_v60he, x)
+
+void ScummEngine_v60he::setupOpcodes() {
+ static const OpcodeEntryv60he opcodes[256] = {
+ /* 00 */
+ OPCODE(o6_pushByte),
+ OPCODE(o6_pushWord),
+ OPCODE(o6_pushByteVar),
+ OPCODE(o6_pushWordVar),
+ /* 04 */
+ OPCODE(o6_invalid),
+ OPCODE(o6_invalid),
+ OPCODE(o6_byteArrayRead),
+ OPCODE(o6_wordArrayRead),
+ /* 08 */
+ OPCODE(o6_invalid),
+ OPCODE(o6_invalid),
+ OPCODE(o6_byteArrayIndexedRead),
+ OPCODE(o6_wordArrayIndexedRead),
+ /* 0C */
+ OPCODE(o6_dup),
+ OPCODE(o6_not),
+ OPCODE(o6_eq),
+ OPCODE(o6_neq),
+ /* 10 */
+ OPCODE(o6_gt),
+ OPCODE(o6_lt),
+ OPCODE(o6_le),
+ OPCODE(o6_ge),
+ /* 14 */
+ OPCODE(o6_add),
+ OPCODE(o6_sub),
+ OPCODE(o6_mul),
+ OPCODE(o6_div),
+ /* 18 */
+ OPCODE(o6_land),
+ OPCODE(o6_lor),
+ OPCODE(o6_pop),
+ OPCODE(o6_invalid),
+ /* 1C */
+ OPCODE(o6_invalid),
+ OPCODE(o6_invalid),
+ OPCODE(o6_invalid),
+ OPCODE(o6_invalid),
+ /* 20 */
+ OPCODE(o6_invalid),
+ OPCODE(o6_invalid),
+ OPCODE(o6_invalid),
+ OPCODE(o6_invalid),
+ /* 24 */
+ OPCODE(o6_invalid),
+ OPCODE(o6_invalid),
+ OPCODE(o6_invalid),
+ OPCODE(o6_invalid),
+ /* 28 */
+ OPCODE(o6_invalid),
+ OPCODE(o6_invalid),
+ OPCODE(o6_invalid),
+ OPCODE(o6_invalid),
+ /* 2C */
+ OPCODE(o6_invalid),
+ OPCODE(o6_invalid),
+ OPCODE(o6_invalid),
+ OPCODE(o6_invalid),
+ /* 30 */
+ OPCODE(o6_invalid),
+ OPCODE(o6_invalid),
+ OPCODE(o6_invalid),
+ OPCODE(o6_invalid),
+ /* 34 */
+ OPCODE(o6_invalid),
+ OPCODE(o6_invalid),
+ OPCODE(o6_invalid),
+ OPCODE(o6_invalid),
+ /* 38 */
+ OPCODE(o6_invalid),
+ OPCODE(o6_invalid),
+ OPCODE(o6_invalid),
+ OPCODE(o6_invalid),
+ /* 3C */
+ OPCODE(o6_invalid),
+ OPCODE(o6_invalid),
+ OPCODE(o6_invalid),
+ OPCODE(o6_invalid),
+ /* 40 */
+ OPCODE(o6_invalid),
+ OPCODE(o6_invalid),
+ OPCODE(o6_writeByteVar),
+ OPCODE(o6_writeWordVar),
+ /* 44 */
+ OPCODE(o6_invalid),
+ OPCODE(o6_invalid),
+ OPCODE(o6_byteArrayWrite),
+ OPCODE(o6_wordArrayWrite),
+ /* 48 */
+ OPCODE(o6_invalid),
+ OPCODE(o6_invalid),
+ OPCODE(o6_byteArrayIndexedWrite),
+ OPCODE(o6_wordArrayIndexedWrite),
+ /* 4C */
+ OPCODE(o6_invalid),
+ OPCODE(o6_invalid),
+ OPCODE(o6_byteVarInc),
+ OPCODE(o6_wordVarInc),
+ /* 50 */
+ OPCODE(o6_invalid),
+ OPCODE(o6_invalid),
+ OPCODE(o6_byteArrayInc),
+ OPCODE(o6_wordArrayInc),
+ /* 54 */
+ OPCODE(o6_invalid),
+ OPCODE(o6_invalid),
+ OPCODE(o6_byteVarDec),
+ OPCODE(o6_wordVarDec),
+ /* 58 */
+ OPCODE(o6_invalid),
+ OPCODE(o6_invalid),
+ OPCODE(o6_byteArrayDec),
+ OPCODE(o6_wordArrayDec),
+ /* 5C */
+ OPCODE(o6_if),
+ OPCODE(o6_ifNot),
+ OPCODE(o6_startScript),
+ OPCODE(o6_startScriptQuick),
+ /* 60 */
+ OPCODE(o6_startObject),
+ OPCODE(o6_drawObject),
+ OPCODE(o6_drawObjectAt),
+ OPCODE(o6_invalid),
+ /* 64 */
+ OPCODE(o6_invalid),
+ OPCODE(o6_stopObjectCode),
+ OPCODE(o6_stopObjectCode),
+ OPCODE(o6_endCutscene),
+ /* 68 */
+ OPCODE(o6_cutscene),
+ OPCODE(o6_stopMusic),
+ OPCODE(o6_freezeUnfreeze),
+ OPCODE(o6_cursorCommand),
+ /* 6C */
+ OPCODE(o6_breakHere),
+ OPCODE(o6_ifClassOfIs),
+ OPCODE(o6_setClass),
+ OPCODE(o6_getState),
+ /* 70 */
+ OPCODE(o60_setState),
+ OPCODE(o6_setOwner),
+ OPCODE(o6_getOwner),
+ OPCODE(o6_jump),
+ /* 74 */
+ OPCODE(o6_startSound),
+ OPCODE(o6_stopSound),
+ OPCODE(o6_startMusic),
+ OPCODE(o6_stopObjectScript),
+ /* 78 */
+ OPCODE(o6_panCameraTo),
+ OPCODE(o6_actorFollowCamera),
+ OPCODE(o6_setCameraAt),
+ OPCODE(o6_loadRoom),
+ /* 7C */
+ OPCODE(o6_stopScript),
+ OPCODE(o6_walkActorToObj),
+ OPCODE(o6_walkActorTo),
+ OPCODE(o6_putActorAtXY),
+ /* 80 */
+ OPCODE(o6_putActorAtObject),
+ OPCODE(o6_faceActor),
+ OPCODE(o6_animateActor),
+ OPCODE(o6_doSentence),
+ /* 84 */
+ OPCODE(o6_pickupObject),
+ OPCODE(o6_loadRoomWithEgo),
+ OPCODE(o6_invalid),
+ OPCODE(o6_getRandomNumber),
+ /* 88 */
+ OPCODE(o6_getRandomNumberRange),
+ OPCODE(o6_invalid),
+ OPCODE(o6_getActorMoving),
+ OPCODE(o6_isScriptRunning),
+ /* 8C */
+ OPCODE(o6_getActorRoom),
+ OPCODE(o6_getObjectX),
+ OPCODE(o6_getObjectY),
+ OPCODE(o6_getObjectOldDir),
+ /* 90 */
+ OPCODE(o6_getActorWalkBox),
+ OPCODE(o6_getActorCostume),
+ OPCODE(o6_findInventory),
+ OPCODE(o6_getInventoryCount),
+ /* 94 */
+ OPCODE(o6_getVerbFromXY),
+ OPCODE(o6_beginOverride),
+ OPCODE(o6_endOverride),
+ OPCODE(o6_setObjectName),
+ /* 98 */
+ OPCODE(o6_isSoundRunning),
+ OPCODE(o6_setBoxFlags),
+ OPCODE(o6_invalid),
+ OPCODE(o6_resourceRoutines),
+ /* 9C */
+ OPCODE(o60_roomOps),
+ OPCODE(o60_actorOps),
+ OPCODE(o6_verbOps),
+ OPCODE(o6_getActorFromXY),
+ /* A0 */
+ OPCODE(o6_findObject),
+ OPCODE(o6_pseudoRoom),
+ OPCODE(o6_getActorElevation),
+ OPCODE(o6_getVerbEntrypoint),
+ /* A4 */
+ OPCODE(o6_arrayOps),
+ OPCODE(o6_saveRestoreVerbs),
+ OPCODE(o6_drawBox),
+ OPCODE(o6_pop),
+ /* A8 */
+ OPCODE(o6_getActorWidth),
+ OPCODE(o6_wait),
+ OPCODE(o6_getActorScaleX),
+ OPCODE(o6_getActorAnimCounter1),
+ /* AC */
+ OPCODE(o6_invalid),
+ OPCODE(o6_isAnyOf),
+ OPCODE(o6_systemOps),
+ OPCODE(o6_isActorInBox),
+ /* B0 */
+ OPCODE(o6_delay),
+ OPCODE(o6_delaySeconds),
+ OPCODE(o6_delayMinutes),
+ OPCODE(o6_stopSentence),
+ /* B4 */
+ OPCODE(o6_printLine),
+ OPCODE(o6_printText),
+ OPCODE(o6_printDebug),
+ OPCODE(o6_printSystem),
+ /* B8 */
+ OPCODE(o6_printActor),
+ OPCODE(o6_printEgo),
+ OPCODE(o6_talkActor),
+ OPCODE(o6_talkEgo),
+ /* BC */
+ OPCODE(o6_dimArray),
+ OPCODE(o6_stopObjectCode),
+ OPCODE(o6_startObjectQuick),
+ OPCODE(o6_startScriptQuick2),
+ /* C0 */
+ OPCODE(o6_dim2dimArray),
+ OPCODE(o6_invalid),
+ OPCODE(o6_invalid),
+ OPCODE(o6_invalid),
+ /* C4 */
+ OPCODE(o6_abs),
+ OPCODE(o6_distObjectObject),
+ OPCODE(o6_distObjectPt),
+ OPCODE(o6_distPtPt),
+ /* C8 */
+ OPCODE(o60_kernelGetFunctions),
+ OPCODE(o60_kernelSetFunctions),
+ OPCODE(o6_delayFrames),
+ OPCODE(o6_pickOneOf),
+ /* CC */
+ OPCODE(o6_pickOneOfDefault),
+ OPCODE(o6_stampObject),
+ OPCODE(o6_invalid),
+ OPCODE(o6_invalid),
+ /* D0 */
+ OPCODE(o6_getDateTime),
+ OPCODE(o6_stopTalking),
+ OPCODE(o6_getAnimateVariable),
+ OPCODE(o6_invalid),
+ /* D4 */
+ OPCODE(o6_shuffle),
+ OPCODE(o6_jumpToScript),
+ OPCODE(o6_band),
+ OPCODE(o6_bor),
+ /* D8 */
+ OPCODE(o6_isRoomScriptRunning),
+ OPCODE(o60_closeFile),
+ OPCODE(o60_openFile),
+ OPCODE(o60_readFile),
+ /* DC */
+ OPCODE(o60_writeFile),
+ OPCODE(o6_findAllObjects),
+ OPCODE(o60_deleteFile),
+ OPCODE(o60_rename),
+ /* E0 */
+ OPCODE(o60_soundOps),
+ OPCODE(o6_getPixel),
+ OPCODE(o60_localizeArrayToScript),
+ OPCODE(o6_pickVarRandom),
+ /* E4 */
+ OPCODE(o6_setBoxSet),
+ OPCODE(o6_invalid),
+ OPCODE(o6_invalid),
+ OPCODE(o6_invalid),
+ /* E8 */
+ OPCODE(o6_invalid),
+ OPCODE(o60_seekFilePos),
+ OPCODE(o60_redimArray),
+ OPCODE(o60_readFilePos),
+ /* EC */
+ OPCODE(o6_invalid),
+ OPCODE(o6_invalid),
+ OPCODE(o6_invalid),
+ OPCODE(o6_invalid),
+ /* F0 */
+ OPCODE(o6_invalid),
+ OPCODE(o6_invalid),
+ OPCODE(o6_invalid),
+ OPCODE(o6_invalid),
+ /* F4 */
+ OPCODE(o6_invalid),
+ OPCODE(o6_invalid),
+ OPCODE(o6_invalid),
+ OPCODE(o6_invalid),
+ /* F8 */
+ OPCODE(o6_invalid),
+ OPCODE(o6_invalid),
+ OPCODE(o6_invalid),
+ OPCODE(o6_invalid),
+ /* FC */
+ OPCODE(o6_invalid),
+ OPCODE(o6_invalid),
+ OPCODE(o6_invalid),
+ OPCODE(o6_invalid),
+ };
+
+ _opcodesv60he = opcodes;
+}
+
+void ScummEngine_v60he::executeOpcode(byte i) {
+ OpcodeProcv60he op = _opcodesv60he[i].proc;
+ (this->*op) ();
+}
+
+const char *ScummEngine_v60he::getOpcodeDesc(byte i) {
+ return _opcodesv60he[i].desc;
+}
+
+void ScummEngine_v60he::o60_setState() {
+ int state = pop();
+ int obj = pop();
+
+ if (state & 0x8000) {
+ state &= 0x7FFF;
+ putState(obj, state);
+ if (_heversion >= 72)
+ removeObjectFromDrawQue(obj);
+ } else {
+ putState(obj, state);
+ markObjectRectAsDirty(obj);
+ if (_bgNeedsRedraw)
+ clearDrawObjectQueue();
+ }
+}
+
+void ScummEngine_v60he::o60_roomOps() {
+ int a, b, c, d, e;
+
+ byte subOp = fetchScriptByte();
+
+ switch (subOp) {
+ case 172: // SO_ROOM_SCROLL
+ b = pop();
+ a = pop();
+ if (a < (_screenWidth / 2))
+ a = (_screenWidth / 2);
+ if (b < (_screenWidth / 2))
+ b = (_screenWidth / 2);
+ if (a > _roomWidth - (_screenWidth / 2))
+ a = _roomWidth - (_screenWidth / 2);
+ if (b > _roomWidth - (_screenWidth / 2))
+ b = _roomWidth - (_screenWidth / 2);
+ VAR(VAR_CAMERA_MIN_X) = a;
+ VAR(VAR_CAMERA_MAX_X) = b;
+ break;
+
+ case 174: // SO_ROOM_SCREEN
+ b = pop();
+ a = pop();
+ if (_heversion >= 71)
+ initScreens(a, _screenHeight);
+ else
+ initScreens(a, b);
+ break;
+
+ case 175: // SO_ROOM_PALETTE
+ d = pop();
+ c = pop();
+ b = pop();
+ a = pop();
+ setPalColor(d, a, b, c);
+ break;
+
+ case 176: // SO_ROOM_SHAKE_ON
+ setShake(1);
+ break;
+
+ case 177: // SO_ROOM_SHAKE_OFF
+ setShake(0);
+ break;
+
+ case 179: // SO_ROOM_INTENSITY
+ c = pop();
+ b = pop();
+ a = pop();
+ darkenPalette(a, a, a, b, c);
+ break;
+
+ case 180: // SO_ROOM_SAVEGAME
+ _saveTemporaryState = true;
+ _saveLoadSlot = pop();
+ _saveLoadFlag = pop();
+ break;
+
+ case 181: // SO_ROOM_FADE
+ a = pop();
+ if (_heversion >= 70) {
+ // Defaults to 1 but doesn't use fade effects
+ } else if (a) {
+ _switchRoomEffect = (byte)(a & 0xFF);
+ _switchRoomEffect2 = (byte)(a >> 8);
+ } else {
+ fadeIn(_newEffect);
+ }
+ break;
+
+ case 182: // SO_RGB_ROOM_INTENSITY
+ e = pop();
+ d = pop();
+ c = pop();
+ b = pop();
+ a = pop();
+ darkenPalette(a, b, c, d, e);
+ break;
+
+ case 183: // SO_ROOM_SHADOW
+ e = pop();
+ d = pop();
+ c = pop();
+ b = pop();
+ a = pop();
+ if (_heversion == 60)
+ setupShadowPalette(a, b, c, d, e, 0, 256);
+ break;
+
+ case 186: // SO_ROOM_TRANSFORM
+ d = pop();
+ c = pop();
+ b = pop();
+ a = pop();
+ palManipulateInit(a, b, c, d);
+ break;
+
+ case 187: // SO_CYCLE_SPEED
+ b = pop();
+ a = pop();
+ checkRange(16, 1, a, "o60_roomOps: 187: color cycle out of range (%d)");
+ _colorCycle[a - 1].delay = (b != 0) ? 0x4000 / (b * 0x4C) : 0;
+ break;
+
+ case 213: // SO_ROOM_NEW_PALETTE
+ a = pop();
+ setPalette(a);
+ break;
+ case 220:
+ a = pop();
+ b = pop();
+ copyPalColor(a, b);
+ break;
+ case 221:
+ int len;
+ len = resStrLen(_scriptPointer);
+ _scriptPointer += len + 1;
+ _saveLoadFlag = pop();
+ _saveLoadSlot = 1;
+ _saveTemporaryState = true;
+ break;
+ case 234: // HE 7.2
+ b = pop();
+ a = pop();
+ swapObjects(a, b);
+ break;
+ case 236: // HE 7.2
+ b = pop();
+ a = pop();
+ setRoomPalette(a, b);
+ break;
+ default:
+ error("o60_roomOps: default case %d", subOp);
+ }
+}
+
+void ScummEngine_v60he::swapObjects(int object1, int object2) {
+ int idx1 = -1, idx2 = -1;
+
+ for (int i = 0; i < _numLocalObjects; i++) {
+ if (_objs[i].obj_nr == object1)
+ idx1 = i;
+
+ if (_objs[i].obj_nr == object2)
+ idx2 = i;
+ }
+
+ if (idx1 == -1 || idx2 == -1 || idx1 <= idx2)
+ return;
+
+ stopObjectScript(object1);
+ stopObjectScript(object2);
+
+ ObjectData tmpOd;
+
+ memcpy(&tmpOd, &_objs[idx1], sizeof(tmpOd));
+ memcpy(&_objs[idx1], &_objs[idx2], sizeof(tmpOd));
+ memcpy(&_objs[idx2], &tmpOd, sizeof(tmpOd));
+}
+
+void ScummEngine_v60he::o60_actorOps() {
+ Actor *a;
+ int i, j, k;
+ int args[8];
+
+ byte subOp = fetchScriptByte();
+ if (subOp == 197) {
+ _curActor = pop();
+ return;
+ }
+
+ a = derefActorSafe(_curActor, "o60_actorOps");
+ if (!a)
+ return;
+
+ switch (subOp) {
+ case 30:
+ // _heversion >= 70
+ _actorClipOverride.bottom = pop();
+ _actorClipOverride.right = pop();
+ _actorClipOverride.top = pop();
+ _actorClipOverride.left = pop();
+ break;
+ case 76: // SO_COSTUME
+ a->setActorCostume(pop());
+ break;
+ case 77: // SO_STEP_DIST
+ j = pop();
+ i = pop();
+ a->setActorWalkSpeed(i, j);
+ break;
+ case 78: // SO_SOUND
+ k = getStackList(args, ARRAYSIZE(args));
+ for (i = 0; i < k; i++)
+ a->_sound[i] = args[i];
+ break;
+ case 79: // SO_WALK_ANIMATION
+ a->_walkFrame = pop();
+ break;
+ case 80: // SO_TALK_ANIMATION
+ a->_talkStopFrame = pop();
+ a->_talkStartFrame = pop();
+ break;
+ case 81: // SO_STAND_ANIMATION
+ a->_standFrame = pop();
+ break;
+ case 82: // SO_ANIMATION
+ // dummy case in scumm6
+ pop();
+ pop();
+ pop();
+ break;
+ case 83: // SO_DEFAULT
+ a->initActor(0);
+ break;
+ case 84: // SO_ELEVATION
+ a->setElevation(pop());
+ break;
+ case 85: // SO_ANIMATION_DEFAULT
+ a->_initFrame = 1;
+ a->_walkFrame = 2;
+ a->_standFrame = 3;
+ a->_talkStartFrame = 4;
+ a->_talkStopFrame = 5;
+ break;
+ case 86: // SO_PALETTE
+ j = pop();
+ i = pop();
+ checkRange(255, 0, i, "Illegal palette slot %d");
+ a->remapActorPaletteColor(i, j);
+ a->_needRedraw = true;
+ break;
+ case 87: // SO_TALK_COLOR
+ a->_talkColor = pop();
+ break;
+ case 88: // SO_ACTOR_NAME
+ loadPtrToResource(rtActorName, a->_number, NULL);
+ break;
+ case 89: // SO_INIT_ANIMATION
+ a->_initFrame = pop();
+ break;
+ case 91: // SO_ACTOR_WIDTH
+ a->_width = pop();
+ break;
+ case 92: // SO_SCALE
+ i = pop();
+ a->setScale(i, i);
+ break;
+ case 93: // SO_NEVER_ZCLIP
+ a->_forceClip = 0;
+ break;
+ case 94: // SO_ALWAYS_ZCLIP
+ a->_forceClip = pop();
+ break;
+ case 95: // SO_IGNORE_BOXES
+ a->_ignoreBoxes = 1;
+ a->_forceClip = 0;
+ if (a->isInCurrentRoom())
+ a->putActor(a->_pos.x, a->_pos.y, a->_room);
+ break;
+ case 96: // SO_FOLLOW_BOXES
+ a->_ignoreBoxes = 0;
+ a->_forceClip = 0;
+ if (a->isInCurrentRoom())
+ a->putActor(a->_pos.x, a->_pos.y, a->_room);
+ break;
+ case 97: // SO_ANIMATION_SPEED
+ a->setAnimSpeed(pop());
+ break;
+ case 98: // SO_SHADOW
+ a->_shadowMode = pop();
+ a->_needRedraw = true;
+ break;
+ case 99: // SO_TEXT_OFFSET
+ a->_talkPosY = pop();
+ a->_talkPosX = pop();
+ break;
+ case 156: // HE 7.2
+ a->_charset = pop();
+ break;
+ case 198: // SO_ACTOR_VARIABLE
+ i = pop();
+ a->setAnimVar(pop(), i);
+ break;
+ case 215: // SO_ACTOR_IGNORE_TURNS_ON
+ a->_ignoreTurns = true;
+ break;
+ case 216: // SO_ACTOR_IGNORE_TURNS_OFF
+ a->_ignoreTurns = false;
+ break;
+ case 217: // SO_ACTOR_NEW
+ a->initActor(2);
+ break;
+ case 218:
+ a->drawActorToBackBuf(a->_pos.x, a->_pos.y);
+ break;
+ case 219:
+ a->_drawToBackBuf = false;
+ a->_needRedraw = true;
+ a->_needBgReset = true;
+ break;
+ case 225:
+ {
+ byte string[128];
+ copyScriptString(string);
+ int slot = pop();
+
+ int len = resStrLen(string) + 1;
+ convertMessageToString(string, a->_heTalkQueue[slot].sentence, len);
+
+ a->_heTalkQueue[slot].posX = a->_talkPosX;
+ a->_heTalkQueue[slot].posY = a->_talkPosY;
+ a->_heTalkQueue[slot].color = a->_talkColor;
+ break;
+ }
+ default:
+ error("o60_actorOps: default case %d", subOp);
+ }
+}
+
+void ScummEngine_v60he::o60_kernelSetFunctions() {
+ int args[29];
+ int num;
+
+ num = getStackList(args, ARRAYSIZE(args));
+
+ switch (args[0]) {
+ case 1:
+ // Used to restore images when decorating cake in
+ // Fatty Bear's Birthday Surprise
+ virtScreenLoad(args[1], args[2], args[3], args[4], args[5]);
+ break;
+ case 3:
+ case 4:
+ case 5:
+ case 6:
+ case 8:
+ //Used before mini games in 3DO versions, seems safe to ignore.
+ break;
+ default:
+ error("o60_kernelSetFunctions: default case %d (param count %d)", args[0], num);
+ }
+}
+
+void ScummEngine_v60he::virtScreenLoad(int resIdx, int x1, int y1, int x2, int y2) {
+ vsUnpackCtx ctx;
+ memset(&ctx, 0, sizeof(ctx));
+ VirtScreen &vs = virtscr[kMainVirtScreen];
+
+ ArrayHeader *ah = (ArrayHeader *)getResourceAddress(rtString, resIdx);
+ virtScreenLoadUnpack(&ctx, ah->data);
+ for (int j = y1; j <= y2; ++j) {
+ uint8 *p1 = vs.getPixels(x1, j - vs.topline);
+ uint8 *p2 = vs.getBackPixels(x1, j - vs.topline);
+ if (x2 >= x1) {
+ uint32 w = x2 - x1 + 1;
+ while (w--) {
+ uint8 decByte = virtScreenLoadUnpack(&ctx, 0);
+ *p1++ = decByte;
+ *p2++ = decByte;
+ }
+ }
+ }
+ markRectAsDirty(kMainVirtScreen, x1, x2, y1, y2 + 1, USAGE_BIT_RESTORED);
+}
+
+uint8 virtScreenLoadUnpack(vsUnpackCtx *ctx, byte *data) {
+ uint8 decByte;
+ if (data != 0) {
+ ctx->type = 0;
+ ctx->ptr = data;
+ decByte = 0;
+ } else {
+ uint8 a;
+ if (ctx->type == 0) {
+ a = *(ctx->ptr)++;
+ if (a & 1) {
+ ctx->type = 1;
+ ctx->b = *(ctx->ptr)++;
+ } else {
+ ctx->type = 2;
+ }
+ ctx->size = a;
+ a = (a >> 1) + 1;
+ } else {
+ a = ctx->size;
+ }
+ if (ctx->type == 2) {
+ ctx->b = *(ctx->ptr)++;
+ }
+ ctx->size = a - 1;
+ if (ctx->size == 0) {
+ ctx->type = 0;
+ }
+ decByte = ctx->b;
+ }
+ return decByte;
+}
+
+
+void ScummEngine_v60he::o60_kernelGetFunctions() {
+ int args[29];
+ ArrayHeader *ah;
+ getStackList(args, ARRAYSIZE(args));
+
+ switch (args[0]) {
+ case 1:
+ // Used to store images when decorating cake in
+ // Fatty Bear's Birthday Surprise
+ writeVar(0, 0);
+ ah = defineArray(0, kByteArray, 0, virtScreenSave(0, args[1], args[2], args[3], args[4]));
+ virtScreenSave(ah->data, args[1], args[2], args[3], args[4]);
+ push(readVar(0));
+ break;
+ default:
+ error("o60_kernelGetFunctions: default case %d", args[0]);
+ }
+}
+
+int ScummEngine_v60he::virtScreenSave(byte *dst, int x1, int y1, int x2, int y2) {
+ int packedSize = 0;
+ VirtScreen &vs = virtscr[kMainVirtScreen];
+
+ for (int j = y1; j <= y2; ++j) {
+ uint8 *p = vs.getBackPixels(x1, j - vs.topline);
+
+ int size = virtScreenSavePack(dst, p, x2 - x1 + 1, 0);
+ if (dst != 0) {
+ dst += size;
+ }
+ packedSize += size;
+ }
+ return packedSize;
+}
+
+int virtScreenSavePack(byte *dst, byte *src, int len, int unk) {
+ vsPackCtx ctx;
+ memset(&ctx, 0, sizeof(ctx));
+
+ uint8 prevByte, curByte;
+
+ ctx.buf[0] = prevByte = *src++;
+ int flag = 0;
+ int iend = 1;
+ int ibeg = 0;
+
+ for (--len; len != 0; --len, prevByte = curByte) {
+ bool pass = false;
+
+ assert(iend < 0x100);
+ ctx.buf[iend] = curByte = *src++;
+ ++iend;
+
+ if (flag == 0) {
+ if (iend > 0x80) {
+ virtScreenSavePackBuf(&ctx, dst, iend - 1);
+ ctx.buf[0] = curByte;
+ iend = 1;
+ ibeg = 0;
+ continue;
+ }
+ if (prevByte != curByte) {
+ ibeg = iend - 1;
+ continue;
+ }
+ if (iend - ibeg < 3) {
+ if (ibeg != 0) {
+ pass = true;
+ } else {
+ flag = 1;
+ }
+ } else {
+ if (ibeg > 0) {
+ virtScreenSavePackBuf(&ctx, dst, ibeg);
+ }
+ flag = 1;
+ }
+ }
+ if (flag == 1 || pass) {
+ if (prevByte != curByte || iend - ibeg > 0x80) {
+ virtScreenSavePackByte(&ctx, dst, iend - ibeg - 1, prevByte);
+ ctx.buf[0] = curByte;
+ iend = 1;
+ ibeg = 0;
+ flag = 0;
+ }
+ }
+ }
+
+ if (flag == 0) {
+ virtScreenSavePackBuf(&ctx, dst, iend);
+ } else if (flag == 1) {
+ virtScreenSavePackByte(&ctx, dst, iend - ibeg, prevByte);
+ }
+ return ctx.size;
+}
+
+void virtScreenSavePackBuf(vsPackCtx *ctx, uint8 *&dst, int len) {
+ if (dst) {
+ *dst++ = (len - 1) * 2;
+ }
+ ++ctx->size;
+ if (len > 0) {
+ ctx->size += len;
+ if (dst) {
+ memcpy(dst, ctx->buf, len);
+ dst += len;
+ }
+ }
+}
+
+void virtScreenSavePackByte(vsPackCtx *ctx, uint8 *&dst, int len, uint8 b) {
+ if (dst) {
+ *dst++ = ((len - 1) * 2) | 1;
+ }
+ ++ctx->size;
+ if (dst) {
+ *dst++ = b;
+ }
+ ++ctx->size;
+}
+
+void ScummEngine_v60he::o60_openFile() {
+ int mode, len, slot, l, r;
+ byte filename[100];
+
+ convertMessageToString(_scriptPointer, filename, sizeof(filename));
+
+ len = resStrLen(_scriptPointer);
+ _scriptPointer += len + 1;
+
+ for (r = strlen((char*)filename); r != 0; r--) {
+ if (filename[r - 1] == '\\')
+ break;
+ }
+
+ mode = pop();
+ slot = -1;
+ for (l = 0; l < 17; l++) {
+ if (_hFileTable[l].isOpen() == false) {
+ slot = l;
+ break;
+ }
+ }
+
+ if (slot != -1) {
+ switch(mode) {
+ case 1:
+ _hFileTable[slot].open((char*)filename + r, Common::File::kFileReadMode, _saveFileMan->getSavePath());
+ if (_hFileTable[slot].isOpen() == false)
+ _hFileTable[slot].open((char*)filename + r, Common::File::kFileReadMode);
+ break;
+ case 2:
+ _hFileTable[slot].open((char*)filename + r, Common::File::kFileWriteMode, _saveFileMan->getSavePath());
+ break;
+ default:
+ error("o60_openFile(): wrong open file mode %d", mode);
+ }
+
+ if (_hFileTable[slot].isOpen() == false)
+ slot = -1;
+
+ }
+ push(slot);
+}
+
+void ScummEngine_v60he::o60_closeFile() {
+ int slot = pop();
+ if (slot != -1)
+ _hFileTable[slot].close();
+}
+
+void ScummEngine_v60he::o60_deleteFile() {
+ int len, r;
+ byte filename[100];
+
+ convertMessageToString(_scriptPointer, filename, sizeof(filename));
+
+ len = resStrLen(_scriptPointer);
+ _scriptPointer += len + 1;
+
+ for (r = strlen((char*)filename); r != 0; r--) {
+ if (filename[r - 1] == '\\')
+ break;
+ }
+
+ debug(1, "stub o60_deleteFile(\"%s\")", filename + r);
+}
+
+void ScummEngine_v60he::o60_rename() {
+ int len, r1, r2;
+ byte filename[100],filename2[100];
+
+ convertMessageToString(_scriptPointer, filename, sizeof(filename));
+
+ len = resStrLen(_scriptPointer);
+ _scriptPointer += len + 1;
+
+ for (r1 = strlen((char*)filename); r1 != 0; r1--) {
+ if (filename[r1 - 1] == '\\')
+ break;
+ }
+
+ convertMessageToString(_scriptPointer, filename2, sizeof(filename2));
+
+ len = resStrLen(_scriptPointer);
+ _scriptPointer += len + 1;
+
+ for (r2 = strlen((char*)filename2); r2 != 0; r2--) {
+ if (filename2[r2 - 1] == '\\')
+ break;
+ }
+
+ debug(1, "stub o60_rename(\"%s\" to \"%s\")", filename + r1, filename2 + r2);
+}
+
+int ScummEngine_v60he::readFileToArray(int slot, int32 size) {
+ if (size == 0)
+ size = _hFileTable[slot].size() - _hFileTable[slot].pos();
+
+ writeVar(0, 0);
+
+ ArrayHeader *ah = defineArray(0, kByteArray, 0, size);
+ _hFileTable[slot].read(ah->data, size);
+
+ return readVar(0);
+}
+
+void ScummEngine_v60he::o60_readFile() {
+ int32 size = pop();
+ int slot = pop();
+ int val;
+
+ // Fatty Bear uses positive values
+ if ((_platform == Common::kPlatformPC) && (_gameId == GID_FBEAR))
+ size = -size;
+
+ if (size == -2) {
+ val = _hFileTable[slot].readUint16LE();
+ push(val);
+ } else if (size == -1) {
+ val = _hFileTable[slot].readByte();
+ push(val);
+ } else {
+ val = readFileToArray(slot, size);
+ push(val);
+ }
+}
+
+void ScummEngine_v60he::writeFileFromArray(int slot, int resID) {
+ ArrayHeader *ah = (ArrayHeader *)getResourceAddress(rtString, resID);
+ int32 size = FROM_LE_16(ah->dim1) * FROM_LE_16(ah->dim2);
+
+ _hFileTable[slot].write(ah->data, size);
+}
+
+void ScummEngine_v60he::o60_writeFile() {
+ int32 size = pop();
+ int16 resID = pop();
+ int slot = pop();
+
+ // Fatty Bear uses positive values
+ if ((_platform == Common::kPlatformPC) && (_gameId == GID_FBEAR))
+ size = -size;
+
+ if (size == -2) {
+ _hFileTable[slot].writeUint16LE(resID);
+ } else if (size == -1) {
+ _hFileTable[slot].writeByte(resID);
+ } else {
+ writeFileFromArray(slot, resID);
+ }
+}
+
+void ScummEngine_v60he::o60_soundOps() {
+ byte subOp = fetchScriptByte();
+ int arg = pop();
+
+ switch (subOp) {
+ case 0xde:
+ _imuse->setMusicVolume(arg);
+ break;
+ case 0xdf:
+ // Used in fbear introduction
+ break;
+ case 0xe0:
+ // Fatty Bear's Birthday surprise uses this when playing the
+ // piano, but only when using one of the digitized instruments.
+ // See also o6_startSound().
+ _sound->setOverrideFreq(arg);
+ break;
+ default:
+ error("o60_soundOps: default case 0x%x", subOp);
+ }
+}
+
+void ScummEngine_v60he::localizeArray(int slot, byte scriptSlot) {
+ if (_heversion >= 80)
+ slot &= ~0x33539000;
+
+ if (slot >= _numArray)
+ error("o60_localizeArrayToScript(%d): array slot out of range", slot);
+
+ _arraySlot[slot] = scriptSlot;
+}
+
+void ScummEngine_v60he::o60_localizeArrayToScript() {
+ int slot = pop();
+ localizeArray(slot, _currentScript);
+}
+
+void ScummEngine_v60he::o60_seekFilePos() {
+ int mode, offset, slot;
+
+ mode = pop();
+ offset = pop();
+ slot = pop();
+
+ if (slot == -1)
+ return;
+
+ switch (mode) {
+ case 1:
+ _hFileTable[slot].seek(offset, SEEK_SET);
+ break;
+ case 2:
+ _hFileTable[slot].seek(offset, SEEK_CUR);
+ break;
+ case 3:
+ _hFileTable[slot].seek(offset, SEEK_END);
+ break;
+ default:
+ error("o60_seekFilePos: default case %d", mode);
+ }
+}
+
+void ScummEngine_v60he::o60_readFilePos() {
+ int slot = pop();
+
+ if (slot == -1) {
+ push(0);
+ return;
+ }
+
+ push(_hFileTable[slot].pos());
+}
+
+void ScummEngine_v60he::o60_redimArray() {
+ int newX, newY;
+ newY = pop();
+ newX = pop();
+
+ if (newY == 0)
+ SWAP(newX, newY);
+
+ byte subOp = fetchScriptByte();
+ switch (subOp) {
+ case 199:
+ redimArray(fetchScriptWord(), newX, newY, kIntArray);
+ break;
+ case 202:
+ redimArray(fetchScriptWord(), newX, newY, kByteArray);
+ break;
+ default:
+ error("o60_redimArray: default type %d", subOp);
+ }
+}
+
+void ScummEngine_v60he::redimArray(int arrayId, int newX, int newY, int type) {
+ // Used in mini game at Cosmic Dust Diner in puttmoon
+ int newSize, oldSize;
+
+ if (readVar(arrayId) == 0)
+ error("redimArray: Reference to zeroed array pointer");
+
+ ArrayHeader *ah = (ArrayHeader *)getResourceAddress(rtString, readVar(arrayId));
+
+ if (!ah)
+ error("redimArray: Invalid array (%d) reference", readVar(arrayId));
+
+ newSize = (type == kIntArray) ? 2 : 1;
+ oldSize = (ah->type == kIntArray) ? 2 : 1;
+
+ newSize *= (newX + 1) * (newY + 1);
+ oldSize *= FROM_LE_16(ah->dim1) * FROM_LE_16(ah->dim2);
+
+ if (newSize != oldSize)
+ error("redimArray: array %d redim mismatch", readVar(arrayId));
+
+ ah->type = TO_LE_16(type);
+ ah->dim1 = TO_LE_16(newY + 1);
+ ah->dim2 = TO_LE_16(newX + 1);
+}
+
+void ScummEngine_v60he::decodeParseString(int m, int n) {
+ int i, colors;
+ int args[31];
+
+ byte b = fetchScriptByte();
+
+ switch (b) {
+ case 65: // SO_AT
+ _string[m].ypos = pop();
+ _string[m].xpos = pop();
+ _string[m].overhead = false;
+ break;
+ case 66: // SO_COLOR
+ _string[m].color = pop();
+ break;
+ case 67: // SO_CLIPPED
+ _string[m].right = pop();
+ break;
+ case 69: // SO_CENTER
+ _string[m].center = true;
+ _string[m].overhead = false;
+ break;
+ case 71: // SO_LEFT
+ _string[m].center = false;
+ _string[m].overhead = false;
+ break;
+ case 72: // SO_OVERHEAD
+ _string[m].overhead = true;
+ _string[m].no_talk_anim = false;
+ break;
+ case 74: // SO_MUMBLE
+ _string[m].no_talk_anim = true;
+ break;
+ case 75: // SO_TEXTSTRING
+ printString(m, _scriptPointer);
+ _scriptPointer += resStrLen(_scriptPointer) + 1;
+ break;
+ case 0xF9:
+ colors = pop();
+ if (colors == 1) {
+ _string[m].color = pop();
+ } else {
+ push(colors);
+ getStackList(args, ARRAYSIZE(args));
+ for (i = 0; i < 16; i++)
+ _charsetColorMap[i] = _charsetData[_string[1]._default.charset][i] = (unsigned char)args[i];
+ _string[m].color = _charsetColorMap[0];
+ }
+ break;
+ case 0xFE:
+ _string[m].loadDefault();
+ if (n)
+ _actorToPrintStrFor = pop();
+ break;
+ case 0xFF:
+ _string[m].saveDefault();
+ break;
+ default:
+ error("decodeParseString: default case 0x%x", b);
+ }
+}
+
+} // End of namespace Scumm
Deleted: scummvm/trunk/engines/scumm/he/script_v6he.cpp
===================================================================
--- scummvm/trunk/engines/scumm/he/script_v6he.cpp 2006-02-15 18:48:56 UTC (rev 20702)
+++ scummvm/trunk/engines/scumm/he/script_v6he.cpp 2006-02-15 18:48:49 UTC (rev 20703)
@@ -1,1276 +0,0 @@
-/* ScummVM - Scumm Interpreter
- * Copyright (C) 2001 Ludvig Strigeus
- * Copyright (C) 2001-2006 The ScummVM project
- *
- * 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/stdafx.h"
-#include "common/savefile.h"
-
-#include "scumm/actor.h"
-#include "scumm/charset.h"
-#include "scumm/imuse.h"
-#include "scumm/he/intern_he.h"
-#include "scumm/object.h"
-#include "scumm/resource.h"
-#include "scumm/scumm.h"
-#include "scumm/sound.h"
-#include "scumm/usage_bits.h"
-#include "scumm/util.h"
-#include "scumm/verbs.h"
-
-namespace Scumm {
-
-struct vsUnpackCtx {
- uint8 size;
- uint8 type;
- uint8 b;
- uint8 *ptr;
-};
-
-struct vsPackCtx {
- int size;
- uint8 buf[256];
-};
-
-static void virtScreenSavePackBuf(vsPackCtx *ctx, uint8 *&dst, int len);
-static void virtScreenSavePackByte(vsPackCtx *ctx, uint8 *&dst, int len, uint8 b);
-static uint8 virtScreenLoadUnpack(vsUnpackCtx *ctx, byte *data);
-static int virtScreenSavePack(byte *dst, byte *src, int len, int unk);
-
-// Compatibility notes:
-//
-// FBEAR (fbear, fbeardemo)
-// transparency in akos.cpp
-// negative size in file read/write
-
-#define OPCODE(x) _OPCODE(ScummEngine_v60he, x)
-
-void ScummEngine_v60he::setupOpcodes() {
- static const OpcodeEntryv60he opcodes[256] = {
- /* 00 */
- OPCODE(o6_pushByte),
- OPCODE(o6_pushWord),
- OPCODE(o6_pushByteVar),
- OPCODE(o6_pushWordVar),
- /* 04 */
- OPCODE(o6_invalid),
- OPCODE(o6_invalid),
- OPCODE(o6_byteArrayRead),
- OPCODE(o6_wordArrayRead),
- /* 08 */
- OPCODE(o6_invalid),
- OPCODE(o6_invalid),
- OPCODE(o6_byteArrayIndexedRead),
- OPCODE(o6_wordArrayIndexedRead),
- /* 0C */
- OPCODE(o6_dup),
- OPCODE(o6_not),
- OPCODE(o6_eq),
- OPCODE(o6_neq),
- /* 10 */
- OPCODE(o6_gt),
- OPCODE(o6_lt),
- OPCODE(o6_le),
- OPCODE(o6_ge),
- /* 14 */
- OPCODE(o6_add),
- OPCODE(o6_sub),
- OPCODE(o6_mul),
- OPCODE(o6_div),
- /* 18 */
- OPCODE(o6_land),
- OPCODE(o6_lor),
- OPCODE(o6_pop),
- OPCODE(o6_invalid),
- /* 1C */
- OPCODE(o6_invalid),
- OPCODE(o6_invalid),
- OPCODE(o6_invalid),
- OPCODE(o6_invalid),
- /* 20 */
- OPCODE(o6_invalid),
- OPCODE(o6_invalid),
- OPCODE(o6_invalid),
- OPCODE(o6_invalid),
- /* 24 */
- OPCODE(o6_invalid),
- OPCODE(o6_invalid),
- OPCODE(o6_invalid),
- OPCODE(o6_invalid),
- /* 28 */
- OPCODE(o6_invalid),
- OPCODE(o6_invalid),
- OPCODE(o6_invalid),
- OPCODE(o6_invalid),
- /* 2C */
- OPCODE(o6_invalid),
- OPCODE(o6_invalid),
- OPCODE(o6_invalid),
- OPCODE(o6_invalid),
- /* 30 */
- OPCODE(o6_invalid),
- OPCODE(o6_invalid),
- OPCODE(o6_invalid),
- OPCODE(o6_invalid),
- /* 34 */
- OPCODE(o6_invalid),
- OPCODE(o6_invalid),
- OPCODE(o6_invalid),
- OPCODE(o6_invalid),
- /* 38 */
- OPCODE(o6_invalid),
- OPCODE(o6_invalid),
- OPCODE(o6_invalid),
- OPCODE(o6_invalid),
- /* 3C */
- OPCODE(o6_invalid),
- OPCODE(o6_invalid),
- OPCODE(o6_invalid),
- OPCODE(o6_invalid),
- /* 40 */
- OPCODE(o6_invalid),
- OPCODE(o6_invalid),
- OPCODE(o6_writeByteVar),
- OPCODE(o6_writeWordVar),
- /* 44 */
- OPCODE(o6_invalid),
- OPCODE(o6_invalid),
- OPCODE(o6_byteArrayWrite),
- OPCODE(o6_wordArrayWrite),
- /* 48 */
- OPCODE(o6_invalid),
- OPCODE(o6_invalid),
- OPCODE(o6_byteArrayIndexedWrite),
- OPCODE(o6_wordArrayIndexedWrite),
- /* 4C */
- OPCODE(o6_invalid),
- OPCODE(o6_invalid),
- OPCODE(o6_byteVarInc),
- OPCODE(o6_wordVarInc),
- /* 50 */
- OPCODE(o6_invalid),
- OPCODE(o6_invalid),
- OPCODE(o6_byteArrayInc),
- OPCODE(o6_wordArrayInc),
- /* 54 */
- OPCODE(o6_invalid),
- OPCODE(o6_invalid),
- OPCODE(o6_byteVarDec),
- OPCODE(o6_wordVarDec),
- /* 58 */
- OPCODE(o6_invalid),
- OPCODE(o6_invalid),
- OPCODE(o6_byteArrayDec),
- OPCODE(o6_wordArrayDec),
- /* 5C */
- OPCODE(o6_if),
- OPCODE(o6_ifNot),
- OPCODE(o6_startScript),
- OPCODE(o6_startScriptQuick),
- /* 60 */
- OPCODE(o6_startObject),
- OPCODE(o6_drawObject),
- OPCODE(o6_drawObjectAt),
- OPCODE(o6_invalid),
- /* 64 */
- OPCODE(o6_invalid),
- OPCODE(o6_stopObjectCode),
- OPCODE(o6_stopObjectCode),
- OPCODE(o6_endCutscene),
- /* 68 */
- OPCODE(o6_cutscene),
- OPCODE(o6_stopMusic),
- OPCODE(o6_freezeUnfreeze),
- OPCODE(o6_cursorCommand),
- /* 6C */
- OPCODE(o6_breakHere),
- OPCODE(o6_ifClassOfIs),
- OPCODE(o6_setClass),
- OPCODE(o6_getState),
- /* 70 */
- OPCODE(o60_setState),
- OPCODE(o6_setOwner),
- OPCODE(o6_getOwner),
- OPCODE(o6_jump),
- /* 74 */
- OPCODE(o6_startSound),
- OPCODE(o6_stopSound),
- OPCODE(o6_startMusic),
- OPCODE(o6_stopObjectScript),
- /* 78 */
- OPCODE(o6_panCameraTo),
- OPCODE(o6_actorFollowCamera),
- OPCODE(o6_setCameraAt),
- OPCODE(o6_loadRoom),
- /* 7C */
- OPCODE(o6_stopScript),
- OPCODE(o6_walkActorToObj),
- OPCODE(o6_walkActorTo),
- OPCODE(o6_putActorAtXY),
- /* 80 */
- OPCODE(o6_putActorAtObject),
- OPCODE(o6_faceActor),
- OPCODE(o6_animateActor),
- OPCODE(o6_doSentence),
- /* 84 */
- OPCODE(o6_pickupObject),
- OPCODE(o6_loadRoomWithEgo),
- OPCODE(o6_invalid),
- OPCODE(o6_getRandomNumber),
- /* 88 */
- OPCODE(o6_getRandomNumberRange),
- OPCODE(o6_invalid),
- OPCODE(o6_getActorMoving),
- OPCODE(o6_isScriptRunning),
- /* 8C */
- OPCODE(o6_getActorRoom),
- OPCODE(o6_getObjectX),
- OPCODE(o6_getObjectY),
- OPCODE(o6_getObjectOldDir),
- /* 90 */
- OPCODE(o6_getActorWalkBox),
- OPCODE(o6_getActorCostume),
- OPCODE(o6_findInventory),
- OPCODE(o6_getInventoryCount),
- /* 94 */
- OPCODE(o6_getVerbFromXY),
- OPCODE(o6_beginOverride),
- OPCODE(o6_endOverride),
- OPCODE(o6_setObjectName),
- /* 98 */
- OPCODE(o6_isSoundRunning),
- OPCODE(o6_setBoxFlags),
- OPCODE(o6_invalid),
- OPCODE(o6_resourceRoutines),
- /* 9C */
- OPCODE(o60_roomOps),
- OPCODE(o60_actorOps),
- OPCODE(o6_verbOps),
- OPCODE(o6_getActorFromXY),
- /* A0 */
- OPCODE(o6_findObject),
- OPCODE(o6_pseudoRoom),
- OPCODE(o6_getActorElevation),
- OPCODE(o6_getVerbEntrypoint),
- /* A4 */
- OPCODE(o6_arrayOps),
- OPCODE(o6_saveRestoreVerbs),
- OPCODE(o6_drawBox),
- OPCODE(o6_pop),
- /* A8 */
- OPCODE(o6_getActorWidth),
- OPCODE(o6_wait),
- OPCODE(o6_getActorScaleX),
- OPCODE(o6_getActorAnimCounter1),
- /* AC */
- OPCODE(o6_invalid),
- OPCODE(o6_isAnyOf),
- OPCODE(o6_systemOps),
- OPCODE(o6_isActorInBox),
- /* B0 */
- OPCODE(o6_delay),
- OPCODE(o6_delaySeconds),
- OPCODE(o6_delayMinutes),
- OPCODE(o6_stopSentence),
- /* B4 */
- OPCODE(o6_printLine),
- OPCODE(o6_printText),
- OPCODE(o6_printDebug),
- OPCODE(o6_printSystem),
- /* B8 */
- OPCODE(o6_printActor),
- OPCODE(o6_printEgo),
- OPCODE(o6_talkActor),
- OPCODE(o6_talkEgo),
- /* BC */
- OPCODE(o6_dimArray),
- OPCODE(o6_stopObjectCode),
- OPCODE(o6_startObjectQuick),
- OPCODE(o6_startScriptQuick2),
- /* C0 */
- OPCODE(o6_dim2dimArray),
- OPCODE(o6_invalid),
- OPCODE(o6_invalid),
- OPCODE(o6_invalid),
- /* C4 */
- OPCODE(o6_abs),
- OPCODE(o6_distObjectObject),
- OPCODE(o6_distObjectPt),
- OPCODE(o6_distPtPt),
- /* C8 */
- OPCODE(o60_kernelGetFunctions),
- OPCODE(o60_kernelSetFunctions),
- OPCODE(o6_delayFrames),
- OPCODE(o6_pickOneOf),
- /* CC */
- OPCODE(o6_pickOneOfDefault),
- OPCODE(o6_stampObject),
- OPCODE(o6_invalid),
- OPCODE(o6_invalid),
- /* D0 */
- OPCODE(o6_getDateTime),
- OPCODE(o6_stopTalking),
- OPCODE(o6_getAnimateVariable),
- OPCODE(o6_invalid),
- /* D4 */
- OPCODE(o6_shuffle),
- OPCODE(o6_jumpToScript),
- OPCODE(o6_band),
- OPCODE(o6_bor),
- /* D8 */
- OPCODE(o6_isRoomScriptRunning),
- OPCODE(o60_closeFile),
- OPCODE(o60_openFile),
- OPCODE(o60_readFile),
- /* DC */
- OPCODE(o60_writeFile),
- OPCODE(o6_findAllObjects),
- OPCODE(o60_deleteFile),
- OPCODE(o60_rename),
- /* E0 */
- OPCODE(o60_soundOps),
- OPCODE(o6_getPixel),
- OPCODE(o60_localizeArrayToScript),
- OPCODE(o6_pickVarRandom),
- /* E4 */
- OPCODE(o6_setBoxSet),
- OPCODE(o6_invalid),
- OPCODE(o6_invalid),
- OPCODE(o6_invalid),
- /* E8 */
- OPCODE(o6_invalid),
- OPCODE(o60_seekFilePos),
- OPCODE(o60_redimArray),
- OPCODE(o60_readFilePos),
- /* EC */
- OPCODE(o6_invalid),
- OPCODE(o6_invalid),
- OPCODE(o6_invalid),
- OPCODE(o6_invalid),
- /* F0 */
- OPCODE(o6_invalid),
- OPCODE(o6_invalid),
- OPCODE(o6_invalid),
- OPCODE(o6_invalid),
- /* F4 */
- OPCODE(o6_invalid),
- OPCODE(o6_invalid),
- OPCODE(o6_invalid),
- OPCODE(o6_invalid),
- /* F8 */
- OPCODE(o6_invalid),
- OPCODE(o6_invalid),
- OPCODE(o6_invalid),
- OPCODE(o6_invalid),
- /* FC */
- OPCODE(o6_invalid),
- OPCODE(o6_invalid),
- OPCODE(o6_invalid),
- OPCODE(o6_invalid),
- };
-
- _opcodesv60he = opcodes;
-}
-
-void ScummEngine_v60he::executeOpcode(byte i) {
- OpcodeProcv60he op = _opcodesv60he[i].proc;
- (this->*op) ();
-}
-
-const char *ScummEngine_v60he::getOpcodeDesc(byte i) {
- return _opcodesv60he[i].desc;
-}
-
-void ScummEngine_v60he::o60_setState() {
- int state = pop();
- int obj = pop();
-
- if (state & 0x8000) {
- state &= 0x7FFF;
- putState(obj, state);
- if (_heversion >= 72)
- removeObjectFromDrawQue(obj);
- } else {
- putState(obj, state);
- markObjectRectAsDirty(obj);
- if (_bgNeedsRedraw)
- clearDrawObjectQueue();
- }
-}
-
-void ScummEngine_v60he::o60_roomOps() {
- int a, b, c, d, e;
-
- byte subOp = fetchScriptByte();
-
- switch (subOp) {
- case 172: // SO_ROOM_SCROLL
- b = pop();
- a = pop();
- if (a < (_screenWidth / 2))
- a = (_screenWidth / 2);
- if (b < (_screenWidth / 2))
- b = (_screenWidth / 2);
- if (a > _roomWidth - (_screenWidth / 2))
- a = _roomWidth - (_screenWidth / 2);
- if (b > _roomWidth - (_screenWidth / 2))
- b = _roomWidth - (_screenWidth / 2);
- VAR(VAR_CAMERA_MIN_X) = a;
- VAR(VAR_CAMERA_MAX_X) = b;
- break;
-
- case 174: // SO_ROOM_SCREEN
- b = pop();
- a = pop();
- if (_heversion >= 71)
- initScreens(a, _screenHeight);
- else
- initScreens(a, b);
- break;
-
- case 175: // SO_ROOM_PALETTE
- d = pop();
- c = pop();
- b = pop();
- a = pop();
- setPalColor(d, a, b, c);
- break;
-
- case 176: // SO_ROOM_SHAKE_ON
- setShake(1);
- break;
-
- case 177: // SO_ROOM_SHAKE_OFF
- setShake(0);
- break;
-
- case 179: // SO_ROOM_INTENSITY
- c = pop();
- b = pop();
- a = pop();
- darkenPalette(a, a, a, b, c);
- break;
-
- case 180: // SO_ROOM_SAVEGAME
- _saveTemporaryState = true;
- _saveLoadSlot = pop();
- _saveLoadFlag = pop();
- break;
-
- case 181: // SO_ROOM_FADE
- a = pop();
- if (_heversion >= 70) {
- // Defaults to 1 but doesn't use fade effects
- } else if (a) {
- _switchRoomEffect = (byte)(a & 0xFF);
- _switchRoomEffect2 = (byte)(a >> 8);
- } else {
- fadeIn(_newEffect);
- }
- break;
-
- case 182: // SO_RGB_ROOM_INTENSITY
- e = pop();
- d = pop();
- c = pop();
- b = pop();
- a = pop();
- darkenPalette(a, b, c, d, e);
- break;
-
- case 183: // SO_ROOM_SHADOW
- e = pop();
- d = pop();
- c = pop();
- b = pop();
- a = pop();
- if (_heversion == 60)
- setupShadowPalette(a, b, c, d, e, 0, 256);
- break;
-
- case 186: // SO_ROOM_TRANSFORM
- d = pop();
- c = pop();
- b = pop();
- a = pop();
- palManipulateInit(a, b, c, d);
- break;
-
- case 187: // SO_CYCLE_SPEED
- b = pop();
- a = pop();
- checkRange(16, 1, a, "o60_roomOps: 187: color cycle out of range (%d)");
- _colorCycle[a - 1].delay = (b != 0) ? 0x4000 / (b * 0x4C) : 0;
- break;
-
- case 213: // SO_ROOM_NEW_PALETTE
- a = pop();
- setPalette(a);
- break;
- case 220:
- a = pop();
- b = pop();
- copyPalColor(a, b);
- break;
- case 221:
- int len;
- len = resStrLen(_scriptPointer);
- _scriptPointer += len + 1;
- _saveLoadFlag = pop();
- _saveLoadSlot = 1;
- _saveTemporaryState = true;
- break;
- case 234: // HE 7.2
- b = pop();
- a = pop();
- swapObjects(a, b);
- break;
- case 236: // HE 7.2
- b = pop();
- a = pop();
- setRoomPalette(a, b);
- break;
- default:
- error("o60_roomOps: default case %d", subOp);
- }
-}
-
-void ScummEngine_v60he::swapObjects(int object1, int object2) {
- int idx1 = -1, idx2 = -1;
-
- for (int i = 0; i < _numLocalObjects; i++) {
- if (_objs[i].obj_nr == object1)
- idx1 = i;
-
- if (_objs[i].obj_nr == object2)
- idx2 = i;
- }
-
- if (idx1 == -1 || idx2 == -1 || idx1 <= idx2)
- return;
-
- stopObjectScript(object1);
- stopObjectScript(object2);
-
- ObjectData tmpOd;
-
- memcpy(&tmpOd, &_objs[idx1], sizeof(tmpOd));
- memcpy(&_objs[idx1], &_objs[idx2], sizeof(tmpOd));
- memcpy(&_objs[idx2], &tmpOd, sizeof(tmpOd));
-}
-
-void ScummEngine_v60he::o60_actorOps() {
- Actor *a;
- int i, j, k;
- int args[8];
-
- byte subOp = fetchScriptByte();
- if (subOp == 197) {
- _curActor = pop();
- return;
- }
-
- a = derefActorSafe(_curActor, "o60_actorOps");
- if (!a)
- return;
-
- switch (subOp) {
- case 30:
- // _heversion >= 70
- _actorClipOverride.bottom = pop();
- _actorClipOverride.right = pop();
- _actorClipOverride.top = pop();
- _actorClipOverride.left = pop();
- break;
- case 76: // SO_COSTUME
- a->setActorCostume(pop());
- break;
- case 77: // SO_STEP_DIST
- j = pop();
- i = pop();
- a->setActorWalkSpeed(i, j);
- break;
- case 78: // SO_SOUND
- k = getStackList(args, ARRAYSIZE(args));
- for (i = 0; i < k; i++)
- a->_sound[i] = args[i];
- break;
- case 79: // SO_WALK_ANIMATION
- a->_walkFrame = pop();
- break;
- case 80: // SO_TALK_ANIMATION
- a->_talkStopFrame = pop();
- a->_talkStartFrame = pop();
- break;
- case 81: // SO_STAND_ANIMATION
- a->_standFrame = pop();
- break;
- case 82: // SO_ANIMATION
- // dummy case in scumm6
- pop();
- pop();
- pop();
- break;
- case 83: // SO_DEFAULT
- a->initActor(0);
- break;
- case 84: // SO_ELEVATION
- a->setElevation(pop());
- break;
- case 85: // SO_ANIMATION_DEFAULT
- a->_initFrame = 1;
- a->_walkFrame = 2;
- a->_standFrame = 3;
- a->_talkStartFrame = 4;
- a->_talkStopFrame = 5;
- break;
- case 86: // SO_PALETTE
- j = pop();
- i = pop();
- checkRange(255, 0, i, "Illegal palette slot %d");
- a->remapActorPaletteColor(i, j);
- a->_needRedraw = true;
- break;
- case 87: // SO_TALK_COLOR
- a->_talkColor = pop();
- break;
- case 88: // SO_ACTOR_NAME
- loadPtrToResource(rtActorName, a->_number, NULL);
- break;
- case 89: // SO_INIT_ANIMATION
- a->_initFrame = pop();
- break;
- case 91: // SO_ACTOR_WIDTH
- a->_width = pop();
- break;
- case 92: // SO_SCALE
- i = pop();
- a->setScale(i, i);
- break;
- case 93: // SO_NEVER_ZCLIP
- a->_forceClip = 0;
- break;
- case 94: // SO_ALWAYS_ZCLIP
- a->_forceClip = pop();
- break;
- case 95: // SO_IGNORE_BOXES
- a->_ignoreBoxes = 1;
- a->_forceClip = 0;
- if (a->isInCurrentRoom())
- a->putActor(a->_pos.x, a->_pos.y, a->_room);
- break;
- case 96: // SO_FOLLOW_BOXES
- a->_ignoreBoxes = 0;
- a->_forceClip = 0;
- if (a->isInCurrentRoom())
- a->putActor(a->_pos.x, a->_pos.y, a->_room);
- break;
- case 97: // SO_ANIMATION_SPEED
- a->setAnimSpeed(pop());
- break;
- case 98: // SO_SHADOW
- a->_shadowMode = pop();
- a->_needRedraw = true;
- break;
- case 99: // SO_TEXT_OFFSET
- a->_talkPosY = pop();
- a->_talkPosX = pop();
- break;
- case 156: // HE 7.2
- a->_charset = pop();
- break;
- case 198: // SO_ACTOR_VARIABLE
- i = pop();
- a->setAnimVar(pop(), i);
- break;
- case 215: // SO_ACTOR_IGNORE_TURNS_ON
- a->_ignoreTurns = true;
- break;
- case 216: // SO_ACTOR_IGNORE_TURNS_OFF
- a->_ignoreTurns = false;
- break;
- case 217: // SO_ACTOR_NEW
- a->initActor(2);
- break;
- case 218:
- a->drawActorToBackBuf(a->_pos.x, a->_pos.y);
- break;
- case 219:
- a->_drawToBackBuf = false;
- a->_needRedraw = true;
- a->_needBgReset = true;
- break;
- case 225:
- {
- byte string[128];
- copyScriptString(string);
- int slot = pop();
-
- int len = resStrLen(string) + 1;
- convertMessageToString(string, a->_heTalkQueue[slot].sentence, len);
-
- a->_heTalkQueue[slot].posX = a->_talkPosX;
- a->_heTalkQueue[slot].posY = a->_talkPosY;
- a->_heTalkQueue[slot].color = a->_talkColor;
- break;
- }
- default:
- error("o60_actorOps: default case %d", subOp);
- }
-}
-
-void ScummEngine_v60he::o60_kernelSetFunctions() {
- int args[29];
- int num;
-
- num = getStackList(args, ARRAYSIZE(args));
-
- switch (args[0]) {
- case 1:
- // Used to restore images when decorating cake in
- // Fatty Bear's Birthday Surprise
- virtScreenLoad(args[1], args[2], args[3], args[4], args[5]);
- break;
- case 3:
- case 4:
- case 5:
- case 6:
- case 8:
- //Used before mini games in 3DO versions, seems safe to ignore.
- break;
- default:
- error("o60_kernelSetFunctions: default case %d (param count %d)", args[0], num);
- }
-}
-
-void ScummEngine_v60he::virtScreenLoad(int resIdx, int x1, int y1, int x2, int y2) {
- vsUnpackCtx ctx;
- memset(&ctx, 0, sizeof(ctx));
- VirtScreen &vs = virtscr[kMainVirtScreen];
-
- ArrayHeader *ah = (ArrayHeader *)getResourceAddress(rtString, resIdx);
- virtScreenLoadUnpack(&ctx, ah->data);
- for (int j = y1; j <= y2; ++j) {
- uint8 *p1 = vs.getPixels(x1, j - vs.topline);
- uint8 *p2 = vs.getBackPixels(x1, j - vs.topline);
- if (x2 >= x1) {
- uint32 w = x2 - x1 + 1;
- while (w--) {
- uint8 decByte = virtScreenLoadUnpack(&ctx, 0);
- *p1++ = decByte;
- *p2++ = decByte;
- }
- }
- }
- markRectAsDirty(kMainVirtScreen, x1, x2, y1, y2 + 1, USAGE_BIT_RESTORED);
-}
-
-uint8 virtScreenLoadUnpack(vsUnpackCtx *ctx, byte *data) {
- uint8 decByte;
- if (data != 0) {
- ctx->type = 0;
- ctx->ptr = data;
- decByte = 0;
- } else {
- uint8 a;
- if (ctx->type == 0) {
- a = *(ctx->ptr)++;
- if (a & 1) {
- ctx->type = 1;
- ctx->b = *(ctx->ptr)++;
- } else {
- ctx->type = 2;
- }
- ctx->size = a;
- a = (a >> 1) + 1;
- } else {
- a = ctx->size;
- }
- if (ctx->type == 2) {
- ctx->b = *(ctx->ptr)++;
- }
- ctx->size = a - 1;
- if (ctx->size == 0) {
- ctx->type = 0;
- }
- decByte = ctx->b;
- }
- return decByte;
-}
-
-
-void ScummEngine_v60he::o60_kernelGetFunctions() {
- int args[29];
- ArrayHeader *ah;
- getStackList(args, ARRAYSIZE(args));
-
- switch (args[0]) {
- case 1:
- // Used to store images when decorating cake in
- // Fatty Bear's Birthday Surprise
- writeVar(0, 0);
- ah = defineArray(0, kByteArray, 0, virtScreenSave(0, args[1], args[2], args[3], args[4]));
- virtScreenSave(ah->data, args[1], args[2], args[3], args[4]);
- push(readVar(0));
- break;
- default:
- error("o60_kernelGetFunctions: default case %d", args[0]);
- }
-}
-
-int ScummEngine_v60he::virtScreenSave(byte *dst, int x1, int y1, int x2, int y2) {
- int packedSize = 0;
- VirtScreen &vs = virtscr[kMainVirtScreen];
-
- for (int j = y1; j <= y2; ++j) {
- uint8 *p = vs.getBackPixels(x1, j - vs.topline);
-
- int size = virtScreenSavePack(dst, p, x2 - x1 + 1, 0);
- if (dst != 0) {
- dst += size;
- }
- packedSize += size;
- }
- return packedSize;
-}
-
-int virtScreenSavePack(byte *dst, byte *src, int len, int unk) {
- vsPackCtx ctx;
- memset(&ctx, 0, sizeof(ctx));
-
- uint8 prevByte, curByte;
-
- ctx.buf[0] = prevByte = *src++;
- int flag = 0;
- int iend = 1;
- int ibeg = 0;
-
- for (--len; len != 0; --len, prevByte = curByte) {
- bool pass = false;
-
- assert(iend < 0x100);
- ctx.buf[iend] = curByte = *src++;
- ++iend;
-
- if (flag == 0) {
- if (iend > 0x80) {
- virtScreenSavePackBuf(&ctx, dst, iend - 1);
- ctx.buf[0] = curByte;
- iend = 1;
- ibeg = 0;
- continue;
- }
- if (prevByte != curByte) {
- ibeg = iend - 1;
- continue;
- }
- if (iend - ibeg < 3) {
- if (ibeg != 0) {
- pass = true;
- } else {
- flag = 1;
- }
- } else {
- if (ibeg > 0) {
- virtScreenSavePackBuf(&ctx, dst, ibeg);
- }
- flag = 1;
- }
- }
- if (flag == 1 || pass) {
- if (prevByte != curByte || iend - ibeg > 0x80) {
- virtScreenSavePackByte(&ctx, dst, iend - ibeg - 1, prevByte);
- ctx.buf[0] = curByte;
- iend = 1;
- ibeg = 0;
- flag = 0;
- }
- }
- }
-
- if (flag == 0) {
- virtScreenSavePackBuf(&ctx, dst, iend);
- } else if (flag == 1) {
- virtScreenSavePackByte(&ctx, dst, iend - ibeg, prevByte);
- }
- return ctx.size;
-}
-
-void virtScreenSavePackBuf(vsPackCtx *ctx, uint8 *&dst, int len) {
- if (dst) {
- *dst++ = (len - 1) * 2;
- }
- ++ctx->size;
- if (len > 0) {
- ctx->size += len;
- if (dst) {
- memcpy(dst, ctx->buf, len);
- dst += len;
- }
- }
-}
-
-void virtScreenSavePackByte(vsPackCtx *ctx, uint8 *&dst, int len, uint8 b) {
- if (dst) {
- *dst++ = ((len - 1) * 2) | 1;
- }
- ++ctx->size;
- if (dst) {
- *dst++ = b;
- }
- ++ctx->size;
-}
-
-void ScummEngine_v60he::o60_openFile() {
- int mode, len, slot, l, r;
- byte filename[100];
-
- convertMessageToString(_scriptPointer, filename, sizeof(filename));
-
- len = resStrLen(_scriptPointer);
- _scriptPointer += len + 1;
-
- for (r = strlen((char*)filename); r != 0; r--) {
- if (filename[r - 1] == '\\')
- break;
- }
-
- mode = pop();
- slot = -1;
- for (l = 0; l < 17; l++) {
- if (_hFileTable[l].isOpen() == false) {
- slot = l;
- break;
- }
- }
-
- if (slot != -1) {
- switch(mode) {
- case 1:
- _hFileTable[slot].open((char*)filename + r, Common::File::kFileReadMode, _saveFileMan->getSavePath());
- if (_hFileTable[slot].isOpen() == false)
- _hFileTable[slot].open((char*)filename + r, Common::File::kFileReadMode);
- break;
- case 2:
- _hFileTable[slot].open((char*)filename + r, Common::File::kFileWriteMode, _saveFileMan->getSavePath());
- break;
- default:
- error("o60_openFile(): wrong open file mode %d", mode);
- }
-
- if (_hFileTable[slot].isOpen() == false)
- slot = -1;
-
- }
- push(slot);
-}
-
-void ScummEngine_v60he::o60_closeFile() {
- int slot = pop();
- if (slot != -1)
- _hFileTable[slot].close();
-}
-
-void ScummEngine_v60he::o60_deleteFile() {
- int len, r;
- byte filename[100];
-
- convertMessageToString(_scriptPointer, filename, sizeof(filename));
-
- len = resStrLen(_scriptPointer);
- _scriptPointer += len + 1;
-
- for (r = strlen((char*)filename); r != 0; r--) {
- if (filename[r - 1] == '\\')
- break;
- }
-
- debug(1, "stub o60_deleteFile(\"%s\")", filename + r);
-}
-
-void ScummEngine_v60he::o60_rename() {
- int len, r1, r2;
- byte filename[100],filename2[100];
-
- convertMessageToString(_scriptPointer, filename, sizeof(filename));
-
- len = resStrLen(_scriptPointer);
- _scriptPointer += len + 1;
-
- for (r1 = strlen((char*)filename); r1 != 0; r1--) {
- if (filename[r1 - 1] == '\\')
- break;
- }
-
- convertMessageToString(_scriptPointer, filename2, sizeof(filename2));
-
- len = resStrLen(_scriptPointer);
- _scriptPointer += len + 1;
-
- for (r2 = strlen((char*)filename2); r2 != 0; r2--) {
- if (filename2[r2 - 1] == '\\')
- break;
- }
-
- debug(1, "stub o60_rename(\"%s\" to \"%s\")", filename + r1, filename2 + r2);
-}
-
-int ScummEngine_v60he::readFileToArray(int slot, int32 size) {
- if (size == 0)
- size = _hFileTable[slot].size() - _hFileTable[slot].pos();
-
- writeVar(0, 0);
-
- ArrayHeader *ah = defineArray(0, kByteArray, 0, size);
- _hFileTable[slot].read(ah->data, size);
-
- return readVar(0);
-}
-
-void ScummEngine_v60he::o60_readFile() {
- int32 size = pop();
- int slot = pop();
- int val;
-
- // Fatty Bear uses positive values
- if ((_platform == Common::kPlatformPC) && (_gameId == GID_FBEAR))
- size = -size;
-
- if (size == -2) {
- val = _hFileTable[slot].readUint16LE();
- push(val);
- } else if (size == -1) {
- val = _hFileTable[slot].readByte();
- push(val);
- } else {
- val = readFileToArray(slot, size);
- push(val);
- }
-}
-
-void ScummEngine_v60he::writeFileFromArray(int slot, int resID) {
- ArrayHeader *ah = (ArrayHeader *)getResourceAddress(rtString, resID);
- int32 size = FROM_LE_16(ah->dim1) * FROM_LE_16(ah->dim2);
-
- _hFileTable[slot].write(ah->data, size);
-}
-
-void ScummEngine_v60he::o60_writeFile() {
- int32 size = pop();
- int16 resID = pop();
- int slot = pop();
-
- // Fatty Bear uses positive values
- if ((_platform == Common::kPlatformPC) && (_gameId == GID_FBEAR))
- size = -size;
-
- if (size == -2) {
- _hFileTable[slot].writeUint16LE(resID);
- } else if (size == -1) {
- _hFileTable[slot].writeByte(resID);
- } else {
- writeFileFromArray(slot, resID);
- }
-}
-
-void ScummEngine_v60he::o60_soundOps() {
- byte subOp = fetchScriptByte();
- int arg = pop();
-
- switch (subOp) {
- case 0xde:
- _imuse->setMusicVolume(arg);
- break;
- case 0xdf:
- // Used in fbear introduction
- break;
- case 0xe0:
- // Fatty Bear's Birthday surprise uses this when playing the
- // piano, but only when using one of the digitized instruments.
- // See also o6_startSound().
- _sound->setOverrideFreq(arg);
- break;
- default:
- error("o60_soundOps: default case 0x%x", subOp);
- }
-}
-
-void ScummEngine_v60he::localizeArray(int slot, byte scriptSlot) {
- if (_heversion >= 80)
- slot &= ~0x33539000;
-
- if (slot >= _numArray)
- error("o60_localizeArrayToScript(%d): array slot out of range", slot);
-
- _arraySlot[slot] = scriptSlot;
-}
-
-void ScummEngine_v60he::o60_localizeArrayToScript() {
- int slot = pop();
- localizeArray(slot, _currentScript);
-}
-
-void ScummEngine_v60he::o60_seekFilePos() {
- int mode, offset, slot;
-
- mode = pop();
- offset = pop();
- slot = pop();
-
- if (slot == -1)
- return;
-
- switch (mode) {
- case 1:
- _hFileTable[slot].seek(offset, SEEK_SET);
- break;
- case 2:
- _hFileTable[slot].seek(offset, SEEK_CUR);
- break;
- case 3:
- _hFileTable[slot].seek(offset, SEEK_END);
- break;
- default:
- error("o60_seekFilePos: default case %d", mode);
- }
-}
-
-void ScummEngine_v60he::o60_readFilePos() {
- int slot = pop();
-
- if (slot == -1) {
- push(0);
- return;
- }
-
- push(_hFileTable[slot].pos());
-}
-
-void ScummEngine_v60he::o60_redimArray() {
- int newX, newY;
- newY = pop();
- newX = pop();
-
- if (newY == 0)
- SWAP(newX, newY);
-
- byte subOp = fetchScriptByte();
- switch (subOp) {
- case 199:
- redimArray(fetchScriptWord(), newX, newY, kIntArray);
- break;
- case 202:
- redimArray(fetchScriptWord(), newX, newY, kByteArray);
- break;
- default:
- error("o60_redimArray: default type %d", subOp);
- }
-}
-
-void ScummEngine_v60he::redimArray(int arrayId, int newX, int newY, int type) {
- // Used in mini game at Cosmic Dust Diner in puttmoon
- int newSize, oldSize;
-
- if (readVar(arrayId) == 0)
- error("redimArray: Reference to zeroed array pointer");
-
- ArrayHeader *ah = (ArrayHeader *)getResourceAddress(rtString, readVar(arrayId));
-
- if (!ah)
- error("redimArray: Invalid array (%d) reference", readVar(arrayId));
-
- newSize = (type == kIntArray) ? 2 : 1;
- oldSize = (ah->type == kIntArray) ? 2 : 1;
-
- newSize *= (newX + 1) * (newY + 1);
- oldSize *= FROM_LE_16(ah->dim1) * FROM_LE_16(ah->dim2);
-
- if (newSize != oldSize)
- error("redimArray: array %d redim mismatch", readVar(arrayId));
-
- ah->type = TO_LE_16(type);
- ah->dim1 = TO_LE_16(newY + 1);
- ah->dim2 = TO_LE_16(newX + 1);
-}
-
-void ScummEngine_v60he::decodeParseString(int m, int n) {
- int i, colors;
- int args[31];
-
- byte b = fetchScriptByte();
-
- switch (b) {
- case 65: // SO_AT
- _string[m].ypos = pop();
- _string[m].xpos = pop();
- _string[m].overhead = false;
- break;
- case 66: // SO_COLOR
- _string[m].color = pop();
- break;
- case 67: // SO_CLIPPED
- _string[m].right = pop();
- break;
- case 69: // SO_CENTER
- _string[m].center = true;
- _string[m].overhead = false;
- break;
- case 71: // SO_LEFT
- _string[m].center = false;
- _string[m].overhead = false;
- break;
- case 72: // SO_OVERHEAD
- _string[m].overhead = true;
- _string[m].no_talk_anim = false;
- break;
- case 74: // SO_MUMBLE
- _string[m].no_talk_anim = true;
- break;
- case 75: // SO_TEXTSTRING
- printString(m, _scriptPointer);
- _scriptPointer += resStrLen(_scriptPointer) + 1;
- break;
- case 0xF9:
- colors = pop();
- if (colors == 1) {
- _string[m].color = pop();
- } else {
- push(colors);
- getStackList(args, ARRAYSIZE(args));
- for (i = 0; i < 16; i++)
- _charsetColorMap[i] = _charsetData[_string[1]._default.charset][i] = (unsigned char)args[i];
- _string[m].color = _charsetColorMap[0];
- }
- break;
- case 0xFE:
- _string[m].loadDefault();
- if (n)
- _actorToPrintStrFor = pop();
- break;
- case 0xFF:
- _string[m].saveDefault();
- break;
- default:
- error("decodeParseString: default case 0x%x", b);
- }
-}
-
-} // End of namespace Scumm
Copied: scummvm/trunk/engines/scumm/he/script_v70he.cpp (from rev 20696, scummvm/trunk/engines/scumm/he/script_v7he.cpp)
===================================================================
--- scummvm/trunk/engines/scumm/he/script_v70he.cpp (rev 0)
+++ scummvm/trunk/engines/scumm/he/script_v70he.cpp 2006-02-15 18:48:49 UTC (rev 20703)
@@ -0,0 +1,1153 @@
+/* ScummVM - Scumm Interpreter
+ * Copyright (C) 2001 Ludvig Strigeus
+ * Copyright (C) 2001-2006 The ScummVM project
+ *
+ * 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/stdafx.h"
+
+#include "common/config-manager.h"
+#include "common/system.h"
+
+#include "scumm/actor.h"
+#include "scumm/charset.h"
+#include "scumm/he/intern_he.h"
+#include "scumm/object.h"
+#include "scumm/resource.h"
+#include "scumm/he/resource_he.h"
+#include "scumm/scumm.h"
+#include "scumm/sound.h"
+#include "scumm/verbs.h"
+
+namespace Scumm {
+
+#define OPCODE(x) _OPCODE(ScummEngine_v70he, x)
+
+void ScummEngine_v70he::setupOpcodes() {
+ static const OpcodeEntryv70he opcodes[256] = {
+ /* 00 */
+ OPCODE(o6_pushByte),
+ OPCODE(o6_pushWord),
+ OPCODE(o6_pushByteVar),
+ OPCODE(o6_pushWordVar),
+ /* 04 */
+ OPCODE(o6_invalid),
+ OPCODE(o6_invalid),
+ OPCODE(o6_byteArrayRead),
+ OPCODE(o6_wordArrayRead),
+ /* 08 */
+ OPCODE(o6_invalid),
+ OPCODE(o6_invalid),
+ OPCODE(o6_byteArrayIndexedRead),
+ OPCODE(o6_wordArrayIndexedRead),
+ /* 0C */
+ OPCODE(o6_dup),
+ OPCODE(o6_not),
+ OPCODE(o6_eq),
+ OPCODE(o6_neq),
+ /* 10 */
+ OPCODE(o6_gt),
+ OPCODE(o6_lt),
+ OPCODE(o6_le),
+ OPCODE(o6_ge),
+ /* 14 */
+ OPCODE(o6_add),
+ OPCODE(o6_sub),
+ OPCODE(o6_mul),
+ OPCODE(o6_div),
+ /* 18 */
+ OPCODE(o6_land),
+ OPCODE(o6_lor),
+ OPCODE(o6_pop),
+ OPCODE(o6_invalid),
+ /* 1C */
+ OPCODE(o6_invalid),
+ OPCODE(o6_invalid),
+ OPCODE(o6_invalid),
+ OPCODE(o6_invalid),
+ /* 20 */
+ OPCODE(o6_invalid),
+ OPCODE(o6_invalid),
+ OPCODE(o6_invalid),
+ OPCODE(o6_invalid),
+ /* 24 */
+ OPCODE(o6_invalid),
+ OPCODE(o6_invalid),
+ OPCODE(o6_invalid),
+ OPCODE(o6_invalid),
+ /* 28 */
+ OPCODE(o6_invalid),
+ OPCODE(o6_invalid),
+ OPCODE(o6_invalid),
+ OPCODE(o6_invalid),
+ /* 2C */
+ OPCODE(o6_invalid),
+ OPCODE(o6_invalid),
+ OPCODE(o6_invalid),
+ OPCODE(o6_invalid),
+ /* 30 */
+ OPCODE(o6_invalid),
+ OPCODE(o6_invalid),
+ OPCODE(o6_invalid),
+ OPCODE(o6_invalid),
+ /* 34 */
+ OPCODE(o6_invalid),
+ OPCODE(o6_invalid),
+ OPCODE(o6_invalid),
+ OPCODE(o6_invalid),
+ /* 38 */
+ OPCODE(o6_invalid),
+ OPCODE(o6_invalid),
+ OPCODE(o6_invalid),
+ OPCODE(o6_invalid),
+ /* 3C */
+ OPCODE(o6_invalid),
+ OPCODE(o6_invalid),
+ OPCODE(o6_invalid),
+ OPCODE(o6_invalid),
+ /* 40 */
+ OPCODE(o6_invalid),
+ OPCODE(o6_invalid),
+ OPCODE(o6_writeByteVar),
+ OPCODE(o6_writeWordVar),
+ /* 44 */
+ OPCODE(o6_invalid),
+ OPCODE(o6_invalid),
+ OPCODE(o6_byteArrayWrite),
+ OPCODE(o6_wordArrayWrite),
+ /* 48 */
+ OPCODE(o6_invalid),
+ OPCODE(o6_invalid),
+ OPCODE(o6_byteArrayIndexedWrite),
+ OPCODE(o6_wordArrayIndexedWrite),
+ /* 4C */
+ OPCODE(o6_invalid),
+ OPCODE(o6_invalid),
+ OPCODE(o6_byteVarInc),
+ OPCODE(o6_wordVarInc),
+ /* 50 */
+ OPCODE(o6_invalid),
+ OPCODE(o6_invalid),
+ OPCODE(o6_byteArrayInc),
+ OPCODE(o6_wordArrayInc),
+ /* 54 */
+ OPCODE(o6_invalid),
+ OPCODE(o6_invalid),
+ OPCODE(o6_byteVarDec),
+ OPCODE(o6_wordVarDec),
+ /* 58 */
+ OPCODE(o6_invalid),
+ OPCODE(o6_invalid),
+ OPCODE(o6_byteArrayDec),
+ OPCODE(o6_wordArrayDec),
+ /* 5C */
+ OPCODE(o6_if),
+ OPCODE(o6_ifNot),
+ OPCODE(o6_startScript),
+ OPCODE(o6_startScriptQuick),
+ /* 60 */
+ OPCODE(o6_startObject),
+ OPCODE(o6_drawObject),
+ OPCODE(o6_drawObjectAt),
+ OPCODE(o6_invalid),
+ /* 64 */
+ OPCODE(o6_invalid),
+ OPCODE(o6_stopObjectCode),
+ OPCODE(o6_stopObjectCode),
+ OPCODE(o6_endCutscene),
+ /* 68 */
+ OPCODE(o6_cutscene),
+ OPCODE(o6_stopMusic),
+ OPCODE(o6_freezeUnfreeze),
+ OPCODE(o6_cursorCommand),
+ /* 6C */
+ OPCODE(o6_breakHere),
+ OPCODE(o6_ifClassOfIs),
+ OPCODE(o6_setClass),
+ OPCODE(o6_getState),
+ /* 70 */
+ OPCODE(o60_setState),
+ OPCODE(o6_setOwner),
+ OPCODE(o6_getOwner),
+ OPCODE(o6_jump),
+ /* 74 */
+ OPCODE(o70_startSound),
+ OPCODE(o6_stopSound),
+ OPCODE(o6_startMusic),
+ OPCODE(o6_stopObjectScript),
+ /* 78 */
+ OPCODE(o6_panCameraTo),
+ OPCODE(o6_actorFollowCamera),
+ OPCODE(o6_setCameraAt),
+ OPCODE(o6_loadRoom),
+ /* 7C */
+ OPCODE(o6_stopScript),
+ OPCODE(o6_walkActorToObj),
+ OPCODE(o6_walkActorTo),
+ OPCODE(o6_putActorAtXY),
+ /* 80 */
+ OPCODE(o6_putActorAtObject),
+ OPCODE(o6_faceActor),
+ OPCODE(o6_animateActor),
+ OPCODE(o6_doSentence),
+ /* 84 */
+ OPCODE(o70_pickupObject),
+ OPCODE(o6_loadRoomWithEgo),
+ OPCODE(o6_invalid),
+ OPCODE(o6_getRandomNumber),
+ /* 88 */
+ OPCODE(o6_getRandomNumberRange),
+ OPCODE(o6_invalid),
+ OPCODE(o6_getActorMoving),
+ OPCODE(o6_isScriptRunning),
+ /* 8C */
+ OPCODE(o70_getActorRoom),
+ OPCODE(o6_getObjectX),
+ OPCODE(o6_getObjectY),
+ OPCODE(o6_getObjectOldDir),
+ /* 90 */
+ OPCODE(o6_getActorWalkBox),
+ OPCODE(o6_getActorCostume),
+ OPCODE(o6_findInventory),
+ OPCODE(o6_getInventoryCount),
+ /* 94 */
+ OPCODE(o6_getVerbFromXY),
+ OPCODE(o6_beginOverride),
+ OPCODE(o6_endOverride),
+ OPCODE(o6_setObjectName),
+ /* 98 */
+ OPCODE(o6_isSoundRunning),
+ OPCODE(o6_setBoxFlags),
+ OPCODE(o6_invalid),
+ OPCODE(o70_resourceRoutines),
+ /* 9C */
+ OPCODE(o60_roomOps),
+ OPCODE(o60_actorOps),
+ OPCODE(o6_verbOps),
+ OPCODE(o6_getActorFromXY),
+ /* A0 */
+ OPCODE(o6_findObject),
+ OPCODE(o6_pseudoRoom),
+ OPCODE(o6_getActorElevation),
+ OPCODE(o6_getVerbEntrypoint),
+ /* A4 */
+ OPCODE(o6_arrayOps),
+ OPCODE(o6_saveRestoreVerbs),
+ OPCODE(o6_drawBox),
+ OPCODE(o6_pop),
+ /* A8 */
+ OPCODE(o6_getActorWidth),
+ OPCODE(o6_wait),
+ OPCODE(o6_getActorScaleX),
+ OPCODE(o6_getActorAnimCounter1),
+ /* AC */
+ OPCODE(o6_invalid),
+ OPCODE(o6_isAnyOf),
+ OPCODE(o70_systemOps),
+ OPCODE(o6_isActorInBox),
+ /* B0 */
+ OPCODE(o6_delay),
+ OPCODE(o6_delaySeconds),
+ OPCODE(o6_delayMinutes),
+ OPCODE(o6_stopSentence),
+ /* B4 */
+ OPCODE(o6_printLine),
+ OPCODE(o6_printText),
+ OPCODE(o6_printDebug),
+ OPCODE(o6_printSystem),
+ /* B8 */
+ OPCODE(o6_printActor),
+ OPCODE(o6_printEgo),
+ OPCODE(o6_talkActor),
+ OPCODE(o6_talkEgo),
+ /* BC */
+ OPCODE(o6_dimArray),
+ OPCODE(o6_stopObjectCode),
+ OPCODE(o6_startObjectQuick),
+ OPCODE(o6_startScriptQuick2),
+ /* C0 */
+ OPCODE(o6_dim2dimArray),
+ OPCODE(o6_invalid),
+ OPCODE(o6_invalid),
+ OPCODE(o6_invalid),
+ /* C4 */
+ OPCODE(o6_abs),
+ OPCODE(o6_distObjectObject),
+ OPCODE(o6_distObjectPt),
+ OPCODE(o6_distPtPt),
+ /* C8 */
+ OPCODE(o60_kernelGetFunctions),
+ OPCODE(o70_kernelSetFunctions),
+ OPCODE(o6_delayFrames),
+ OPCODE(o6_pickOneOf),
+ /* CC */
+ OPCODE(o6_pickOneOfDefault),
+ OPCODE(o6_stampObject),
+ OPCODE(o6_invalid),
+ OPCODE(o6_invalid),
+ /* D0 */
+ OPCODE(o6_getDateTime),
+ OPCODE(o6_stopTalking),
+ OPCODE(o6_getAnimateVariable),
+ OPCODE(o6_invalid),
+ /* D4 */
+ OPCODE(o6_shuffle),
+ OPCODE(o6_jumpToScript),
+ OPCODE(o6_band),
+ OPCODE(o6_bor),
+ /* D8 */
+ OPCODE(o6_isRoomScriptRunning),
+ OPCODE(o60_closeFile),
+ OPCODE(o60_openFile),
+ OPCODE(o60_readFile),
+ /* DC */
+ OPCODE(o60_writeFile),
+ OPCODE(o6_findAllObjects),
+ OPCODE(o60_deleteFile),
+ OPCODE(o60_rename),
+ /* E0 */
+ OPCODE(o60_soundOps),
+ OPCODE(o6_getPixel),
+ OPCODE(o60_localizeArrayToScript),
+ OPCODE(o6_pickVarRandom),
+ /* E4 */
+ OPCODE(o6_setBoxSet),
+ OPCODE(o6_invalid),
+ OPCODE(o6_invalid),
+ OPCODE(o6_invalid),
+ /* E8 */
+ OPCODE(o6_invalid),
+ OPCODE(o70_seekFilePos),
+ OPCODE(o60_redimArray),
+ OPCODE(o60_readFilePos),
+ /* EC */
+ OPCODE(o70_copyString),
+ OPCODE(o70_getStringWidth),
+ OPCODE(o70_getStringLen),
+ OPCODE(o70_appendString),
+ /* F0 */
+ OPCODE(o70_concatString),
+ OPCODE(o70_compareString),
+ OPCODE(o70_isResourceLoaded),
+ OPCODE(o70_readINI),
+ /* F4 */
+ OPCODE(o70_writeINI),
+ OPCODE(o70_getStringLenForWidth),
+ OPCODE(o70_getCharIndexInString),
+ OPCODE(o6_invalid),
+ /* F8 */
+ OPCODE(o6_invalid),
+ OPCODE(o70_setFilePath),
+ OPCODE(o70_setSystemMessage),
+ OPCODE(o70_polygonOps),
+ /* FC */
+ OPCODE(o70_polygonHit),
+ OPCODE(o6_invalid),
+ OPCODE(o6_invalid),
+ OPCODE(o6_invalid),
+ };
+
+ _opcodesv70he = opcodes;
+}
+
+void ScummEngine_v70he::executeOpcode(byte i) {
+ OpcodeProcv70he op = _opcodesv70he[i].proc;
+ (this->*op) ();
+}
+
+const char *ScummEngine_v70he::getOpcodeDesc(byte i) {
+ return _opcodesv70he[i].desc;
+}
+
+int ScummEngine_v70he::getStringCharWidth(byte chr) {
+ int charset = _string[0]._default.charset;
+
+ byte *ptr = getResourceAddress(rtCharset, charset);
+ assert(ptr);
+ ptr += 29;
+
+ int spacing = 0;
+
+ int offs = READ_LE_UINT32(ptr + chr * 4 + 4);
+ if (offs) {
+ spacing = ptr[offs] + (signed char)ptr[offs + 2];
+ }
+
+ return spacing;
+}
+
+int ScummEngine_v70he::setupStringArray(int size) {
+ writeVar(0, 0);
+ defineArray(0, kStringArray, 0, size + 1);
+ writeArray(0, 0, 0, 0);
+ return readVar(0);
+}
+
+void ScummEngine_v70he::appendSubstring(int dst, int src, int srcOffs, int len) {
+ int dstOffs, value;
+ int i = 0;
+
+ if (len == -1) {
+ len = resStrLen(getStringAddress(src));
+ srcOffs = 0;
+ }
+
+ dstOffs = resStrLen(getStringAddress(dst));
+
+ len -= srcOffs;
+ len++;
+
+ while (i < len) {
+ writeVar(0, src);
+ value = readArray(0, 0, srcOffs + i);
+ writeVar(0, dst);
+ writeArray(0, 0, dstOffs + i, value);
+ i++;
+ }
+
+ writeArray(0, 0, dstOffs + i, 0);
+}
+
+void ScummEngine_v70he::o70_startSound() {
+ int var, value;
+
+ byte subOp = fetchScriptByte();
+
+ switch (subOp) {
+ case 9:
+ _heSndFlags |= 4;
+ break;
+ case 23:
+ value = pop();
+ var = pop();
+ _heSndSoundId = pop();
+ _sound->setSoundVar(_heSndSoundId, var, value);
+ break;
+ case 25:
+ value = pop();
+ _heSndSoundId = pop();
+ _sound->addSoundToQueue(_heSndSoundId, 0, 0, 8);
+ case 56:
+ _heSndFlags |= 16;
+ break;
+ case 164:
+ _heSndFlags |= 2;
+ break;
+ case 224:
+ _heSndSoundFreq = pop();
+ break;
+ case 230:
+ _heSndChannel = pop();
+ break;
+ case 231:
+ _heSndOffset = pop();
+ break;
+ case 232:
+ _heSndSoundId = pop();
+ _heSndOffset = 0;
+ _heSndSoundFreq = 11025;
+ _heSndChannel = VAR(VAR_SOUND_CHANNEL);
+ break;
+ case 245:
+ _heSndFlags |= 1;
+ break;
+ case 255:
+ _sound->addSoundToQueue(_heSndSoundId, _heSndOffset, _heSndChannel, _heSndFlags);
+ _heSndFlags = 0;
+ break;
+
+ default:
+ error("o70_startSound invalid case %d", subOp);
+ }
+}
+
+void ScummEngine_v70he::o70_pickupObject() {
+ int obj, room;
+
+ room = pop();
+ obj = pop();
+ if (room == 0)
+ room = getObjectRoom(obj);
+
+ addObjectToInventory(obj, room);
+ putOwner(obj, VAR(VAR_EGO));
+ if (_heversion <= 70) {
+ putClass(obj, kObjectClassUntouchable, 1);
+ putState(obj, 1);
+ markObjectRectAsDirty(obj);
+ clearDrawObjectQueue();
+ }
+ runInventoryScript(obj); /* Difference */
+}
+
+void ScummEngine_v70he::o70_getActorRoom() {
+ int act = pop();
+
+ if (act < _numActors) {
+ Actor *a = derefActor(act, "o70_getActorRoom");
+ push(a->_room);
+ } else
+ push(getObjectRoom(act));
+}
+
+void ScummEngine_v70he::o70_resourceRoutines() {
+ int objidx, resid;
+
+ byte subOp = fetchScriptByte();
+
+ switch (subOp) {
+ case 100: // SO_LOAD_SCRIPT
+ resid = pop();
+ ensureResourceLoaded(rtScript, resid);
+ break;
+ case 101: // SO_LOAD_SOUND
+ resid = pop();
+ ensureResourceLoaded(rtSound, resid);
+ break;
+ case 102: // SO_LOAD_COSTUME
+ resid = pop();
+ ensureResourceLoaded(rtCostume, resid);
+ break;
+ case 103: // SO_LOAD_ROOM
+ resid = pop();
+ ensureResourceLoaded(rtRoomImage, resid);
+ ensureResourceLoaded(rtRoom, resid);
+ break;
+ case 104: // SO_NUKE_SCRIPT
+ resid = pop();
+ res.nukeResource(rtScript, resid);
+ break;
+ case 105: // SO_NUKE_SOUND
+ resid = pop();
+ res.nukeResource(rtSound, resid);
+ break;
+ case 106: // SO_NUKE_COSTUME
+ resid = pop();
+ res.nukeResource(rtCostume, resid);
+ break;
+ case 107: // SO_NUKE_ROOM
+ resid = pop();
+ res.nukeResource(rtRoom, resid);
+ res.nukeResource(rtRoomImage, resid);
+ break;
+ case 108: // SO_LOCK_SCRIPT
+ resid = pop();
+ if (resid >= _numGlobalScripts)
+ break;
+ res.lock(rtScript, resid);
+ break;
+ case 109: // SO_LOCK_SOUND
+ resid = pop();
+ res.lock(rtSound, resid);
+ break;
+ case 110: // SO_LOCK_COSTUME
+ resid = pop();
+ res.lock(rtCostume, resid);
+ break;
+ case 111: // SO_LOCK_ROOM
+ resid = pop();
+ if (_heversion <= 71 && resid > 0x7F)
+ resid = _resourceMapper[resid & 0x7F];
+ res.lock(rtRoom, resid);
+ res.lock(rtRoomImage, resid);
+ break;
+ case 112: // SO_UNLOCK_SCRIPT
+ resid = pop();
+ if (resid >= _numGlobalScripts)
+ break;
+ res.unlock(rtScript, resid);
+ break;
+ case 113: // SO_UNLOCK_SOUND
+ resid = pop();
+ res.unlock(rtSound, resid);
+ break;
+ case 114: // SO_UNLOCK_COSTUME
+ resid = pop();
+ res.unlock(rtCostume, resid);
+ break;
+ case 115: // SO_UNLOCK_ROOM
+ resid = pop();
+ if (_heversion <= 71 && resid > 0x7F)
+ resid = _resourceMapper[resid & 0x7F];
+ res.unlock(rtRoom, resid);
+ res.unlock(rtRoomImage, resid);
+ break;
+ case 116:
+ break;
+ case 117: // SO_LOAD_CHARSET
+ resid = pop();
+ loadCharset(resid);
+ break;
+ case 118: // SO_NUKE_CHARSET
+ resid = pop();
+ nukeCharset(resid);
+ break;
+ case 119: // SO_LOAD_OBJECT
+ {
+ int obj = pop();
+ int room = getObjectRoom(obj);
+ loadFlObject(obj, room);
+ break;
+ }
+ case 120:
+ resid = pop();
+ if (resid >= _numGlobalScripts)
+ break;
+ //queueLoadResource(rtScript, resid);
+ break;
+ case 121:
+ resid = pop();
+ //queueLoadResource(rtSound, resid);
+ break;
+ case 122:
+ resid = pop();
+ //queueLoadResource(rtCostume, resid);
+ break;
+ case 123:
+ resid = pop();
+ //queueLoadResource(rtRoomImage, resid);
+ break;
+ case 159:
+ resid = pop();
+ res.unlock(rtImage, resid);
+ break;
+ case 192:
+ resid = pop();
+ res.nukeResource(rtImage, resid);
+ break;
+ case 201:
+ resid = pop();
+ ensureResourceLoaded(rtImage, resid);
+ break;
+ case 202:
+ resid = pop();
+ res.lock(rtImage, resid);
+ break;
+ case 203:
+ resid = pop();
+ //queueLoadResource(rtImage, resid);
+ break;
+ case 233:
+ resid = pop();
+ objidx = getObjectIndex(resid);
+ if (objidx == -1)
+ break;
+ res.lock(rtFlObject, _objs[objidx].fl_object_index);
+ break;
+ case 235:
+ resid = pop();
+ objidx = getObjectIndex(resid);
+ if (objidx == -1)
+ break;
+ res.unlock(rtFlObject, _objs[objidx].fl_object_index);
+ break;
+ case 239:
+ // Used in airport
+ break;
+ default:
+ error("o70_resourceRoutines: default case %d", subOp);
+ }
+}
+
+void ScummEngine_v70he::o70_systemOps() {
+ byte *src, string[256];
+ int id, len;
+
+ byte subOp = fetchScriptByte();
+
+ switch (subOp) {
+ case 158:
+ restart();
+ break;
+ case 160:
+ // Confirm shutdown
+ shutDown();
+ break;
+ case 244:
+ shutDown();
+ break;
+ case 250:
+ id = pop();
+ src = getStringAddress(id);
+ len = resStrLen(src) + 1;
+ memcpy(string, src, len);
+ debug(0, "Start executable (%s)", string);
+ break;
+ case 251:
+ convertMessageToString(_scriptPointer, string, sizeof(string));
+ len = resStrLen(_scriptPointer);
+ _scriptPointer += len + 1;
+ debug(0, "Start executable (%s)", string);
+ break;
+ case 252:
+ convertMessageToString(_scriptPointer, string, sizeof(string));
+ len = resStrLen(_scriptPointer);
+ _scriptPointer += len + 1;
+ debug(0, "Start game (%s)", string);
+ break;
+ case 253:
+ id = pop();
+ src = getStringAddress(id);
+ len = resStrLen(src) + 1;
+ memcpy(string, src, len);
+ debug(0, "Start game (%s)", string);
+ break;
+ default:
+ error("o70_systemOps invalid case %d", subOp);
+ }
+}
+
+void ScummEngine_v70he::o70_seekFilePos() {
+ int mode, offset, slot;
+ mode = pop();
+ offset = pop();
+ slot = pop();
+
+ if (slot == -1)
+ return;
+
+ switch (mode) {
+ case 1:
+ _hFileTable[slot].seek(offset, SEEK_SET);
+ break;
+ case 2:
+ _hFileTable[slot].seek(offset, SEEK_CUR);
+ break;
+ case 3:
+ _hFileTable[slot].seek(offset, SEEK_END);
+ break;
+ default:
+ error("o70_seekFilePos: default case 0x%x", mode);
+ }
+}
+
+void ScummEngine_v70he::o70_copyString() {
+ int dst, size;
+ int src = pop();
+
+ size = resStrLen(getStringAddress(src)) + 1;
+ dst = setupStringArray(size);
+
+ appendSubstring(dst, src, -1, -1);
+
+ push(dst);
+}
+
+void ScummEngine_v70he::o70_getStringWidth() {
+ int array, pos, len;
+ int chr, width = 0;
+
+ len = pop();
+ pos = pop();
+ array = pop();
+
+ if (len == -1) {
+ pos = 0;
+ len = resStrLen(getStringAddress(array));
+ }
+
+ writeVar(0, array);
+ while (pos <= len) {
+ chr = readArray(0, 0, pos);
+ if (chr == 0)
+ break;
+ width += getStringCharWidth(chr);
+ pos++;
+ }
+
+ push(width);
+}
+
+void ScummEngine_v70he::o70_kernelSetFunctions() {
+ int args[29];
+ int num;
+ Actor *a;
+
+ num = getStackList(args, ARRAYSIZE(args));
+
+ switch (args[0]) {
+ case 1:
+ // Used to restore images when decorating cake in
+ // Fatty Bear's Birthday Surprise
+ virtScreenLoad(args[1], args[2], args[3], args[4], args[5]);
+ break;
+ case 20: // HE72+
+ a = derefActor(args[1], "o70_kernelSetFunctions: 20");
+ ((ScummEngine_v71he *)this)->queueAuxBlock(a);
+ break;
+ case 21:
+ _skipDrawObject = 1;
+ break;
+ case 22:
+ _skipDrawObject = 0;
+ break;
+ case 23:
+ _charset->clearCharsetMask();
+ _fullRedraw = true;
+ break;
+ case 24:
+ _skipProcessActors = 1;
+ redrawAllActors();
+ break;
+ case 25:
+ _skipProcessActors = 0;
+ redrawAllActors();
+ break;
+ case 26:
+ a = derefActor(args[1], "o70_kernelSetFunctions: 26");
+ a->_auxBlock.r.left = 0;
+ a->_auxBlock.r.right = -1;
+ a->_auxBlock.r.top = 0;
+ a->_auxBlock.r.bottom = -2;
+ break;
+ case 30:
+ a = derefActor(args[1], "o70_kernelSetFunctions: 30");
+ a->_clipOverride.bottom = args[2];
+ break;
+ case 42:
+ _wiz->_rectOverrideEnabled = true;
+ _wiz->_rectOverride.left = args[1];
+ _wiz->_rectOverride.top = args[2];
+ _wiz->_rectOverride.right = args[3];
+ _wiz->_rectOverride.bottom = args[4];
+ break;
+ case 43:
+ _wiz->_rectOverrideEnabled = false;
+ break;
+ default:
+ error("o70_kernelSetFunctions: default case %d (param count %d)", args[0], num);
+ }
+}
+
+void ScummEngine_v70he::o70_getStringLen() {
+ int id, len;
+ byte *addr;
+
+ id = pop();
+
+ addr = getStringAddress(id);
+ if (!addr)
+ error("o70_getStringLen: Reference to zeroed array pointer (%d)", id);
+
+ len = resStrLen(getStringAddress(id));
+ push(len);
+}
+
+void ScummEngine_v70he::o70_appendString() {
+ int dst, size;
+
+ int len = pop();
+ int srcOffs = pop();
+ int src = pop();
+
+ size = len - srcOffs + 2;
+ dst = setupStringArray(size);
+
+ appendSubstring(dst, src, srcOffs, len);
+
+ push(dst);
+}
+
+void ScummEngine_v70he::o70_concatString() {
+ int dst, size;
+
+ int src2 = pop();
+ int src1 = pop();
+
+ size = resStrLen(getStringAddress(src1));
+ size += resStrLen(getStringAddress(src2)) + 1;
+ dst = setupStringArray(size);
+
+ appendSubstring(dst, src1, 0, -1);
+ appendSubstring(dst, src2, 0, -1);
+
+ push(dst);
+}
+
+void ScummEngine_v70he::o70_compareString() {
+ int result;
+
+ int array1 = pop();
+ int array2 = pop();
+
+ byte *string1 = getStringAddress(array1);
+ if (!string1)
+ error("o70_compareString: Reference to zeroed array pointer (%d)", array1);
+
+ byte *string2 = getStringAddress(array2);
+ if (!string2)
+ error("o70_compareString: Reference to zeroed array pointer (%d)", array2);
+
+ while (*string1 == *string2) {
+ if (*string2 == 0) {
+ push(0);
+ return;
+ }
+
+ string1++;
+ string2++;
+ }
+
+ result = (*string1 > *string2) ? -1 : 1;
+ push(result);
+}
+
+void ScummEngine_v70he::o70_isResourceLoaded() {
+ // Reports percentage of resource loaded by queue
+ int type;
+
+ byte subOp = fetchScriptByte();
+ /* int idx = */ pop();
+
+ switch (subOp) {
+ case 18:
+ type = rtImage;
+ break;
+ case 226:
+ type = rtRoom;
+ break;
+ case 227:
+ type = rtCostume;
+ break;
+ case 228:
+ type = rtSound;
+ break;
+ case 229:
+ type = rtScript;
+ break;
+ default:
+ error("o70_isResourceLoaded: default case %d", subOp);
+ }
+
+ push(100);
+}
+
+void ScummEngine_v70he::o70_readINI() {
+ byte option[256];
+ ArrayHeader *ah;
+ const char *entry;
+ int len, type;
+
+ convertMessageToString(_scriptPointer, option, sizeof(option));
+ len = resStrLen(_scriptPointer);
+ _scriptPointer += len + 1;
+
+ type = pop();
+ switch (type) {
+ case 1: // number
+ if (!strcmp((char *)option, "NoPrinting")) {
+ push(1);
+ } else if (!strcmp((char *)option, "TextOn")) {
+ push(ConfMan.getBool("subtitles"));
+ } else {
+ push(ConfMan.getInt((char *)option));
+ }
+ break;
+ case 2: // string
+ entry = (ConfMan.get((char *)option).c_str());
+
+ writeVar(0, 0);
+ len = resStrLen((const byte *)entry);
+ ah = defineArray(0, kStringArray, 0, len);
+ memcpy(ah->data, entry, len);
+
+ push(readVar(0));
+ break;
+ default:
+ error("o70_readINI: default type %d", type);
+ }
+ debug(1, "o70_readINI: Option %s", option);
+}
+
+void ScummEngine_v70he::o70_writeINI() {
+ int type, value;
+ byte option[256], string[256];
+ int len;
+
+ type = pop();
+ value = pop();
+
+ convertMessageToString(_scriptPointer, option, sizeof(option));
+ len = resStrLen(_scriptPointer);
+ _scriptPointer += len + 1;
+
+ switch (type) {
+ case 1: // number
+ ConfMan.set((char *)option, value);
+ debug(1, "o70_writeINI: Option %s Value %d", option, value);
+ break;
+ case 2: // string
+ convertMessageToString(_scriptPointer, string, sizeof(string));
+ len = resStrLen(_scriptPointer);
+ _scriptPointer += len + 1;
+ ConfMan.set((char *)option, (char *)string);
+ debug(1, "o70_writeINI: Option %s String %s", option, string);
+ break;
+ default:
+ error("o70_writeINI: default type %d", type);
+ }
+}
+
+void ScummEngine_v70he::o70_getStringLenForWidth() {
+ int chr, max;
+ int array, len, pos, width = 0;
+
+ max = pop();
+ pos = pop();
+ array = pop();
+
+ len = resStrLen(getStringAddress(array));
+
+ writeVar(0, array);
+ while (pos <= len) {
+ chr = readArray(0, 0, pos);
+ width += getStringCharWidth(chr);
+ if (width >= max) {
+ push(pos);
+ return;
+ }
+ pos++;
+ }
+
+ push(len);
+}
+
+void ScummEngine_v70he::o70_getCharIndexInString() {
+ int array, end, len, pos, value;
+
+ value = pop();
+ end = pop();
+ pos = pop();
+ array = pop();
+
+ if (end >= 0) {
+ len = resStrLen(getStringAddress(array));
+ if (len < end)
+ end = len;
+ } else {
+ end = 0;
+ }
+
+ if (pos < 0)
+ pos = 0;
+
+ writeVar(0, array);
+ if (end > pos) {
+ while (end >= pos) {
+ if (readArray(0, 0, pos) == value) {
+ push(pos);
+ return;
+ }
+ pos++;
+ }
+ } else {
+ while (end <= pos) {
+ if (readArray(0, 0, pos) == value) {
+ push(pos);
+ return;
+ }
+ pos--;
+ }
+ }
+
+ push(-1);
+}
+
+void ScummEngine_v70he::o70_setFilePath() {
+ int len;
+ byte filename[100];
+
+ convertMessageToString(_scriptPointer, filename, sizeof(filename));
+ len = resStrLen(_scriptPointer);
+ _scriptPointer += len + 1;
+
+ debug(1,"stub o70_setFilePath(%s)", filename);
+}
+
+void ScummEngine_v70he::o70_setSystemMessage() {
+ int len;
+ byte name[255];
+
+ byte subOp = fetchScriptByte();
+
+ convertMessageToString(_scriptPointer, name, sizeof(name));
+ len = resStrLen(_scriptPointer);
+ _scriptPointer += len + 1;
+
+ switch (subOp) {
+ case 240:
+ debug(1,"o70_setSystemMessage: (%d) %s", subOp, name);
+ break;
+ case 241: // Set Version
+ debug(1,"o70_setSystemMessage: (%d) %s", subOp, name);
+ break;
+ case 242:
+ debug(1,"o70_setSystemMessage: (%d) %s", subOp, name);
+ break;
+ case 243: // Set Window Caption
+ _system->setWindowCaption((const char *)name);
+ break;
+ default:
+ error("o70_setSystemMessage: default case %d", subOp);
+ }
+}
+
+void ScummEngine_v70he::o70_polygonOps() {
+ int vert1x, vert1y, vert2x, vert2y, vert3x, vert3y, vert4x, vert4y;
+ int id, fromId, toId;
+ bool flag;
+
+ byte subOp = fetchScriptByte();
+
+ switch (subOp) {
+ case 68: // HE 100
+ case 69: // HE 100
+ case 246:
+ case 248:
+ vert4y = pop();
+ vert4x = pop();
+ vert3y = pop();
+ vert3x = pop();
+ vert2y = pop();
+ vert2x = pop();
+ vert1y = pop();
+ vert1x = pop();
+ flag = (subOp == 69 || subOp == 248);
+ id = pop();
+ _wiz->polygonStore(id, flag, vert1x, vert1y, vert2x, vert2y, vert3x, vert3y, vert4x, vert4y);
+ break;
+ case 28: // HE 100
+ case 247:
+ toId = pop();
+ fromId = pop();
+ _wiz->polygonErase(fromId, toId);
+ break;
+ default:
+ error("o70_polygonOps: default case %d", subOp);
+ }
+}
+
+void ScummEngine_v70he::o70_polygonHit() {
+ int y = pop();
+ int x = pop();
+ push(_wiz->polygonHit(0, x, y));
+}
+
+} // End of namespace Scumm
Modified: scummvm/trunk/engines/scumm/he/script_v72he.cpp
===================================================================
--- scummvm/trunk/engines/scumm/he/script_v72he.cpp 2006-02-15 18:48:56 UTC (rev 20702)
+++ scummvm/trunk/engines/scumm/he/script_v72he.cpp 2006-02-15 18:48:49 UTC (rev 20703)
@@ -32,7 +32,7 @@
#include "scumm/he/intern_he.h"
#include "scumm/object.h"
#include "scumm/resource.h"
-#include "scumm/he/resource_v7he.h"
+#include "scumm/he/resource_he.h"
#include "scumm/scumm.h"
#include "scumm/sound.h"
#include "scumm/util.h"
Deleted: scummvm/trunk/engines/scumm/he/script_v7he.cpp
===================================================================
--- scummvm/trunk/engines/scumm/he/script_v7he.cpp 2006-02-15 18:48:56 UTC (rev 20702)
+++ scummvm/trunk/engines/scumm/he/script_v7he.cpp 2006-02-15 18:48:49 UTC (rev 20703)
@@ -1,1153 +0,0 @@
-/* ScummVM - Scumm Interpreter
- * Copyright (C) 2001 Ludvig Strigeus
- * Copyright (C) 2001-2006 The ScummVM project
- *
- * 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/stdafx.h"
-
-#include "common/config-manager.h"
-#include "common/system.h"
-
-#include "scumm/actor.h"
-#include "scumm/charset.h"
-#include "scumm/he/intern_he.h"
-#include "scumm/object.h"
-#include "scumm/resource.h"
-#include "scumm/he/resource_v7he.h"
-#include "scumm/scumm.h"
-#include "scumm/sound.h"
-#include "scumm/verbs.h"
-
-namespace Scumm {
-
-#define OPCODE(x) _OPCODE(ScummEngine_v70he, x)
-
-void ScummEngine_v70he::setupOpcodes() {
- static const OpcodeEntryv70he opcodes[256] = {
- /* 00 */
- OPCODE(o6_pushByte),
- OPCODE(o6_pushWord),
- OPCODE(o6_pushByteVar),
- OPCODE(o6_pushWordVar),
- /* 04 */
- OPCODE(o6_invalid),
- OPCODE(o6_invalid),
- OPCODE(o6_byteArrayRead),
- OPCODE(o6_wordArrayRead),
- /* 08 */
- OPCODE(o6_invalid),
- OPCODE(o6_invalid),
- OPCODE(o6_byteArrayIndexedRead),
- OPCODE(o6_wordArrayIndexedRead),
- /* 0C */
- OPCODE(o6_dup),
- OPCODE(o6_not),
- OPCODE(o6_eq),
- OPCODE(o6_neq),
- /* 10 */
- OPCODE(o6_gt),
- OPCODE(o6_lt),
- OPCODE(o6_le),
- OPCODE(o6_ge),
- /* 14 */
- OPCODE(o6_add),
- OPCODE(o6_sub),
- OPCODE(o6_mul),
- OPCODE(o6_div),
- /* 18 */
- OPCODE(o6_land),
- OPCODE(o6_lor),
- OPCODE(o6_pop),
- OPCODE(o6_invalid),
- /* 1C */
- OPCODE(o6_invalid),
- OPCODE(o6_invalid),
- OPCODE(o6_invalid),
- OPCODE(o6_invalid),
- /* 20 */
- OPCODE(o6_invalid),
- OPCODE(o6_invalid),
- OPCODE(o6_invalid),
- OPCODE(o6_invalid),
- /* 24 */
- OPCODE(o6_invalid),
- OPCODE(o6_invalid),
- OPCODE(o6_invalid),
- OPCODE(o6_invalid),
- /* 28 */
- OPCODE(o6_invalid),
- OPCODE(o6_invalid),
- OPCODE(o6_invalid),
- OPCODE(o6_invalid),
- /* 2C */
- OPCODE(o6_invalid),
- OPCODE(o6_invalid),
- OPCODE(o6_invalid),
- OPCODE(o6_invalid),
- /* 30 */
- OPCODE(o6_invalid),
- OPCODE(o6_invalid),
- OPCODE(o6_invalid),
- OPCODE(o6_invalid),
- /* 34 */
- OPCODE(o6_invalid),
- OPCODE(o6_invalid),
- OPCODE(o6_invalid),
- OPCODE(o6_invalid),
- /* 38 */
- OPCODE(o6_invalid),
- OPCODE(o6_invalid),
- OPCODE(o6_invalid),
- OPCODE(o6_invalid),
- /* 3C */
- OPCODE(o6_invalid),
- OPCODE(o6_invalid),
- OPCODE(o6_invalid),
- OPCODE(o6_invalid),
- /* 40 */
- OPCODE(o6_invalid),
- OPCODE(o6_invalid),
- OPCODE(o6_writeByteVar),
- OPCODE(o6_writeWordVar),
- /* 44 */
- OPCODE(o6_invalid),
- OPCODE(o6_invalid),
- OPCODE(o6_byteArrayWrite),
- OPCODE(o6_wordArrayWrite),
- /* 48 */
- OPCODE(o6_invalid),
- OPCODE(o6_invalid),
- OPCODE(o6_byteArrayIndexedWrite),
- OPCODE(o6_wordArrayIndexedWrite),
- /* 4C */
- OPCODE(o6_invalid),
- OPCODE(o6_invalid),
- OPCODE(o6_byteVarInc),
- OPCODE(o6_wordVarInc),
- /* 50 */
- OPCODE(o6_invalid),
- OPCODE(o6_invalid),
- OPCODE(o6_byteArrayInc),
- OPCODE(o6_wordArrayInc),
- /* 54 */
- OPCODE(o6_invalid),
- OPCODE(o6_invalid),
- OPCODE(o6_byteVarDec),
- OPCODE(o6_wordVarDec),
- /* 58 */
- OPCODE(o6_invalid),
- OPCODE(o6_invalid),
- OPCODE(o6_byteArrayDec),
- OPCODE(o6_wordArrayDec),
- /* 5C */
- OPCODE(o6_if),
- OPCODE(o6_ifNot),
- OPCODE(o6_startScript),
- OPCODE(o6_startScriptQuick),
- /* 60 */
- OPCODE(o6_startObject),
- OPCODE(o6_drawObject),
- OPCODE(o6_drawObjectAt),
- OPCODE(o6_invalid),
- /* 64 */
- OPCODE(o6_invalid),
- OPCODE(o6_stopObjectCode),
- OPCODE(o6_stopObjectCode),
- OPCODE(o6_endCutscene),
- /* 68 */
- OPCODE(o6_cutscene),
- OPCODE(o6_stopMusic),
- OPCODE(o6_freezeUnfreeze),
- OPCODE(o6_cursorCommand),
- /* 6C */
- OPCODE(o6_breakHere),
- OPCODE(o6_ifClassOfIs),
- OPCODE(o6_setClass),
- OPCODE(o6_getState),
- /* 70 */
- OPCODE(o60_setState),
- OPCODE(o6_setOwner),
- OPCODE(o6_getOwner),
- OPCODE(o6_jump),
- /* 74 */
- OPCODE(o70_startSound),
- OPCODE(o6_stopSound),
- OPCODE(o6_startMusic),
- OPCODE(o6_stopObjectScript),
- /* 78 */
- OPCODE(o6_panCameraTo),
- OPCODE(o6_actorFollowCamera),
- OPCODE(o6_setCameraAt),
- OPCODE(o6_loadRoom),
- /* 7C */
- OPCODE(o6_stopScript),
- OPCODE(o6_walkActorToObj),
- OPCODE(o6_walkActorTo),
- OPCODE(o6_putActorAtXY),
- /* 80 */
- OPCODE(o6_putActorAtObject),
- OPCODE(o6_faceActor),
- OPCODE(o6_animateActor),
- OPCODE(o6_doSentence),
- /* 84 */
- OPCODE(o70_pickupObject),
- OPCODE(o6_loadRoomWithEgo),
- OPCODE(o6_invalid),
- OPCODE(o6_getRandomNumber),
- /* 88 */
- OPCODE(o6_getRandomNumberRange),
- OPCODE(o6_invalid),
- OPCODE(o6_getActorMoving),
- OPCODE(o6_isScriptRunning),
- /* 8C */
- OPCODE(o70_getActorRoom),
- OPCODE(o6_getObjectX),
- OPCODE(o6_getObjectY),
- OPCODE(o6_getObjectOldDir),
- /* 90 */
- OPCODE(o6_getActorWalkBox),
- OPCODE(o6_getActorCostume),
- OPCODE(o6_findInventory),
- OPCODE(o6_getInventoryCount),
- /* 94 */
- OPCODE(o6_getVerbFromXY),
- OPCODE(o6_beginOverride),
- OPCODE(o6_endOverride),
- OPCODE(o6_setObjectName),
- /* 98 */
- OPCODE(o6_isSoundRunning),
- OPCODE(o6_setBoxFlags),
- OPCODE(o6_invalid),
- OPCODE(o70_resourceRoutines),
- /* 9C */
- OPCODE(o60_roomOps),
- OPCODE(o60_actorOps),
- OPCODE(o6_verbOps),
- OPCODE(o6_getActorFromXY),
- /* A0 */
- OPCODE(o6_findObject),
- OPCODE(o6_pseudoRoom),
- OPCODE(o6_getActorElevation),
- OPCODE(o6_getVerbEntrypoint),
- /* A4 */
- OPCODE(o6_arrayOps),
- OPCODE(o6_saveRestoreVerbs),
- OPCODE(o6_drawBox),
- OPCODE(o6_pop),
- /* A8 */
- OPCODE(o6_getActorWidth),
- OPCODE(o6_wait),
- OPCODE(o6_getActorScaleX),
- OPCODE(o6_getActorAnimCounter1),
- /* AC */
- OPCODE(o6_invalid),
- OPCODE(o6_isAnyOf),
- OPCODE(o70_systemOps),
- OPCODE(o6_isActorInBox),
- /* B0 */
- OPCODE(o6_delay),
- OPCODE(o6_delaySeconds),
- OPCODE(o6_delayMinutes),
- OPCODE(o6_stopSentence),
- /* B4 */
- OPCODE(o6_printLine),
- OPCODE(o6_printText),
- OPCODE(o6_printDebug),
- OPCODE(o6_printSystem),
- /* B8 */
- OPCODE(o6_printActor),
- OPCODE(o6_printEgo),
- OPCODE(o6_talkActor),
- OPCODE(o6_talkEgo),
- /* BC */
- OPCODE(o6_dimArray),
- OPCODE(o6_stopObjectCode),
- OPCODE(o6_startObjectQuick),
- OPCODE(o6_startScriptQuick2),
- /* C0 */
- OPCODE(o6_dim2dimArray),
- OPCODE(o6_invalid),
- OPCODE(o6_invalid),
- OPCODE(o6_invalid),
- /* C4 */
- OPCODE(o6_abs),
- OPCODE(o6_distObjectObject),
- OPCODE(o6_distObjectPt),
- OPCODE(o6_distPtPt),
- /* C8 */
- OPCODE(o60_kernelGetFunctions),
- OPCODE(o70_kernelSetFunctions),
- OPCODE(o6_delayFrames),
- OPCODE(o6_pickOneOf),
- /* CC */
- OPCODE(o6_pickOneOfDefault),
- OPCODE(o6_stampObject),
- OPCODE(o6_invalid),
- OPCODE(o6_invalid),
- /* D0 */
- OPCODE(o6_getDateTime),
- OPCODE(o6_stopTalking),
- OPCODE(o6_getAnimateVariable),
- OPCODE(o6_invalid),
- /* D4 */
- OPCODE(o6_shuffle),
- OPCODE(o6_jumpToScript),
- OPCODE(o6_band),
- OPCODE(o6_bor),
- /* D8 */
- OPCODE(o6_isRoomScriptRunning),
- OPCODE(o60_closeFile),
- OPCODE(o60_openFile),
- OPCODE(o60_readFile),
- /* DC */
- OPCODE(o60_writeFile),
- OPCODE(o6_findAllObjects),
- OPCODE(o60_deleteFile),
- OPCODE(o60_rename),
- /* E0 */
- OPCODE(o60_soundOps),
- OPCODE(o6_getPixel),
- OPCODE(o60_localizeArrayToScript),
- OPCODE(o6_pickVarRandom),
- /* E4 */
- OPCODE(o6_setBoxSet),
- OPCODE(o6_invalid),
- OPCODE(o6_invalid),
- OPCODE(o6_invalid),
- /* E8 */
- OPCODE(o6_invalid),
- OPCODE(o70_seekFilePos),
- OPCODE(o60_redimArray),
- OPCODE(o60_readFilePos),
- /* EC */
- OPCODE(o70_copyString),
- OPCODE(o70_getStringWidth),
- OPCODE(o70_getStringLen),
- OPCODE(o70_appendString),
- /* F0 */
- OPCODE(o70_concatString),
- OPCODE(o70_compareString),
- OPCODE(o70_isResourceLoaded),
- OPCODE(o70_readINI),
- /* F4 */
- OPCODE(o70_writeINI),
- OPCODE(o70_getStringLenForWidth),
- OPCODE(o70_getCharIndexInString),
- OPCODE(o6_invalid),
- /* F8 */
- OPCODE(o6_invalid),
- OPCODE(o70_setFilePath),
- OPCODE(o70_setSystemMessage),
- OPCODE(o70_polygonOps),
- /* FC */
- OPCODE(o70_polygonHit),
- OPCODE(o6_invalid),
- OPCODE(o6_invalid),
- OPCODE(o6_invalid),
- };
-
- _opcodesv70he = opcodes;
-}
-
-void ScummEngine_v70he::executeOpcode(byte i) {
- OpcodeProcv70he op = _opcodesv70he[i].proc;
- (this->*op) ();
-}
-
-const char *ScummEngine_v70he::getOpcodeDesc(byte i) {
- return _opcodesv70he[i].desc;
-}
-
-int ScummEngine_v70he::getStringCharWidth(byte chr) {
- int charset = _string[0]._default.charset;
-
- byte *ptr = getResourceAddress(rtCharset, charset);
- assert(ptr);
- ptr += 29;
-
- int spacing = 0;
-
- int offs = READ_LE_UINT32(ptr + chr * 4 + 4);
- if (offs) {
- spacing = ptr[offs] + (signed char)ptr[offs + 2];
- }
-
- return spacing;
-}
-
-int ScummEngine_v70he::setupStringArray(int size) {
- writeVar(0, 0);
- defineArray(0, kStringArray, 0, size + 1);
- writeArray(0, 0, 0, 0);
- return readVar(0);
-}
-
-void ScummEngine_v70he::appendSubstring(int dst, int src, int srcOffs, int len) {
- int dstOffs, value;
- int i = 0;
-
- if (len == -1) {
- len = resStrLen(getStringAddress(src));
- srcOffs = 0;
- }
-
- dstOffs = resStrLen(getStringAddress(dst));
-
- len -= srcOffs;
- len++;
-
- while (i < len) {
- writeVar(0, src);
- value = readArray(0, 0, srcOffs + i);
- writeVar(0, dst);
- writeArray(0, 0, dstOffs + i, value);
- i++;
- }
-
- writeArray(0, 0, dstOffs + i, 0);
-}
-
-void ScummEngine_v70he::o70_startSound() {
- int var, value;
-
- byte subOp = fetchScriptByte();
-
- switch (subOp) {
- case 9:
- _heSndFlags |= 4;
- break;
- case 23:
- value = pop();
- var = pop();
- _heSndSoundId = pop();
- _sound->setSoundVar(_heSndSoundId, var, value);
- break;
- case 25:
- value = pop();
- _heSndSoundId = pop();
- _sound->addSoundToQueue(_heSndSoundId, 0, 0, 8);
- case 56:
- _heSndFlags |= 16;
- break;
- case 164:
- _heSndFlags |= 2;
- break;
- case 224:
- _heSndSoundFreq = pop();
- break;
- case 230:
- _heSndChannel = pop();
- break;
- case 231:
- _heSndOffset = pop();
- break;
- case 232:
- _heSndSoundId = pop();
- _heSndOffset = 0;
- _heSndSoundFreq = 11025;
- _heSndChannel = VAR(VAR_SOUND_CHANNEL);
- break;
- case 245:
- _heSndFlags |= 1;
- break;
- case 255:
- _sound->addSoundToQueue(_heSndSoundId, _heSndOffset, _heSndChannel, _heSndFlags);
- _heSndFlags = 0;
- break;
-
- default:
- error("o70_startSound invalid case %d", subOp);
- }
-}
-
-void ScummEngine_v70he::o70_pickupObject() {
- int obj, room;
-
- room = pop();
- obj = pop();
- if (room == 0)
- room = getObjectRoom(obj);
-
- addObjectToInventory(obj, room);
- putOwner(obj, VAR(VAR_EGO));
- if (_heversion <= 70) {
- putClass(obj, kObjectClassUntouchable, 1);
- putState(obj, 1);
- markObjectRectAsDirty(obj);
- clearDrawObjectQueue();
- }
- runInventoryScript(obj); /* Difference */
-}
-
-void ScummEngine_v70he::o70_getActorRoom() {
- int act = pop();
-
- if (act < _numActors) {
- Actor *a = derefActor(act, "o70_getActorRoom");
- push(a->_room);
- } else
- push(getObjectRoom(act));
-}
-
-void ScummEngine_v70he::o70_resourceRoutines() {
- int objidx, resid;
-
- byte subOp = fetchScriptByte();
-
- switch (subOp) {
- case 100: // SO_LOAD_SCRIPT
- resid = pop();
- ensureResourceLoaded(rtScript, resid);
- break;
- case 101: // SO_LOAD_SOUND
- resid = pop();
- ensureResourceLoaded(rtSound, resid);
- break;
- case 102: // SO_LOAD_COSTUME
- resid = pop();
- ensureResourceLoaded(rtCostume, resid);
- break;
- case 103: // SO_LOAD_ROOM
- resid = pop();
- ensureResourceLoaded(rtRoomImage, resid);
- ensureResourceLoaded(rtRoom, resid);
- break;
- case 104: // SO_NUKE_SCRIPT
- resid = pop();
- res.nukeResource(rtScript, resid);
- break;
- case 105: // SO_NUKE_SOUND
- resid = pop();
- res.nukeResource(rtSound, resid);
- break;
- case 106: // SO_NUKE_COSTUME
- resid = pop();
- res.nukeResource(rtCostume, resid);
- break;
- case 107: // SO_NUKE_ROOM
- resid = pop();
- res.nukeResource(rtRoom, resid);
- res.nukeResource(rtRoomImage, resid);
- break;
- case 108: // SO_LOCK_SCRIPT
- resid = pop();
- if (resid >= _numGlobalScripts)
- break;
- res.lock(rtScript, resid);
- break;
- case 109: // SO_LOCK_SOUND
- resid = pop();
- res.lock(rtSound, resid);
- break;
- case 110: // SO_LOCK_COSTUME
- resid = pop();
- res.lock(rtCostume, resid);
- break;
- case 111: // SO_LOCK_ROOM
- resid = pop();
- if (_heversion <= 71 && resid > 0x7F)
- resid = _resourceMapper[resid & 0x7F];
- res.lock(rtRoom, resid);
- res.lock(rtRoomImage, resid);
- break;
- case 112: // SO_UNLOCK_SCRIPT
- resid = pop();
- if (resid >= _numGlobalScripts)
- break;
- res.unlock(rtScript, resid);
- break;
- case 113: // SO_UNLOCK_SOUND
- resid = pop();
- res.unlock(rtSound, resid);
- break;
- case 114: // SO_UNLOCK_COSTUME
- resid = pop();
- res.unlock(rtCostume, resid);
- break;
- case 115: // SO_UNLOCK_ROOM
- resid = pop();
- if (_heversion <= 71 && resid > 0x7F)
- resid = _resourceMapper[resid & 0x7F];
- res.unlock(rtRoom, resid);
- res.unlock(rtRoomImage, resid);
- break;
- case 116:
- break;
- case 117: // SO_LOAD_CHARSET
- resid = pop();
- loadCharset(resid);
- break;
- case 118: // SO_NUKE_CHARSET
- resid = pop();
- nukeCharset(resid);
- break;
- case 119: // SO_LOAD_OBJECT
- {
- int obj = pop();
- int room = getObjectRoom(obj);
- loadFlObject(obj, room);
- break;
- }
- case 120:
- resid = pop();
- if (resid >= _numGlobalScripts)
- break;
- //queueLoadResource(rtScript, resid);
- break;
- case 121:
- resid = pop();
- //queueLoadResource(rtSound, resid);
- break;
- case 122:
- resid = pop();
- //queueLoadResource(rtCostume, resid);
- break;
- case 123:
- resid = pop();
- //queueLoadResource(rtRoomImage, resid);
- break;
- case 159:
- resid = pop();
- res.unlock(rtImage, resid);
- break;
- case 192:
- resid = pop();
- res.nukeResource(rtImage, resid);
- break;
- case 201:
- resid = pop();
- ensureResourceLoaded(rtImage, resid);
- break;
- case 202:
- resid = pop();
- res.lock(rtImage, resid);
- break;
- case 203:
- resid = pop();
- //queueLoadResource(rtImage, resid);
- break;
- case 233:
- resid = pop();
- objidx = getObjectIndex(resid);
- if (objidx == -1)
- break;
- res.lock(rtFlObject, _objs[objidx].fl_object_index);
- break;
- case 235:
- resid = pop();
- objidx = getObjectIndex(resid);
- if (objidx == -1)
- break;
- res.unlock(rtFlObject, _objs[objidx].fl_object_index);
- break;
- case 239:
- // Used in airport
- break;
- default:
- error("o70_resourceRoutines: default case %d", subOp);
- }
-}
-
-void ScummEngine_v70he::o70_systemOps() {
- byte *src, string[256];
- int id, len;
-
- byte subOp = fetchScriptByte();
-
- switch (subOp) {
- case 158:
- restart();
- break;
- case 160:
- // Confirm shutdown
- shutDown();
- break;
- case 244:
- shutDown();
- break;
- case 250:
- id = pop();
- src = getStringAddress(id);
- len = resStrLen(src) + 1;
- memcpy(string, src, len);
- debug(0, "Start executable (%s)", string);
- break;
- case 251:
- convertMessageToString(_scriptPointer, string, sizeof(string));
- len = resStrLen(_scriptPointer);
- _scriptPointer += len + 1;
- debug(0, "Start executable (%s)", string);
- break;
- case 252:
- convertMessageToString(_scriptPointer, string, sizeof(string));
- len = resStrLen(_scriptPointer);
- _scriptPointer += len + 1;
- debug(0, "Start game (%s)", string);
- break;
- case 253:
- id = pop();
- src = getStringAddress(id);
- len = resStrLen(src) + 1;
- memcpy(string, src, len);
- debug(0, "Start game (%s)", string);
- break;
- default:
- error("o70_systemOps invalid case %d", subOp);
- }
-}
-
-void ScummEngine_v70he::o70_seekFilePos() {
- int mode, offset, slot;
- mode = pop();
- offset = pop();
- slot = pop();
-
- if (slot == -1)
- return;
-
- switch (mode) {
- case 1:
- _hFileTable[slot].seek(offset, SEEK_SET);
- break;
- case 2:
- _hFileTable[slot].seek(offset, SEEK_CUR);
- break;
- case 3:
- _hFileTable[slot].seek(offset, SEEK_END);
- break;
- default:
- error("o70_seekFilePos: default case 0x%x", mode);
- }
-}
-
-void ScummEngine_v70he::o70_copyString() {
- int dst, size;
- int src = pop();
-
- size = resStrLen(getStringAddress(src)) + 1;
- dst = setupStringArray(size);
-
- appendSubstring(dst, src, -1, -1);
-
- push(dst);
-}
-
-void ScummEngine_v70he::o70_getStringWidth() {
- int array, pos, len;
- int chr, width = 0;
-
- len = pop();
- pos = pop();
- array = pop();
-
- if (len == -1) {
- pos = 0;
- len = resStrLen(getStringAddress(array));
- }
-
- writeVar(0, array);
- while (pos <= len) {
- chr = readArray(0, 0, pos);
- if (chr == 0)
- break;
- width += getStringCharWidth(chr);
- pos++;
- }
-
- push(width);
-}
-
-void ScummEngine_v70he::o70_kernelSetFunctions() {
- int args[29];
- int num;
- Actor *a;
-
- num = getStackList(args, ARRAYSIZE(args));
-
- switch (args[0]) {
- case 1:
- // Used to restore images when decorating cake in
- // Fatty Bear's Birthday Surprise
- virtScreenLoad(args[1], args[2], args[3], args[4], args[5]);
- break;
- case 20: // HE72+
- a = derefActor(args[1], "o70_kernelSetFunctions: 20");
- ((ScummEngine_v71he *)this)->queueAuxBlock(a);
- break;
- case 21:
- _skipDrawObject = 1;
- break;
- case 22:
- _skipDrawObject = 0;
- break;
- case 23:
- _charset->clearCharsetMask();
- _fullRedraw = true;
- break;
- case 24:
- _skipProcessActors = 1;
- redrawAllActors();
- break;
- case 25:
- _skipProcessActors = 0;
- redrawAllActors();
- break;
- case 26:
- a = derefActor(args[1], "o70_kernelSetFunctions: 26");
- a->_auxBlock.r.left = 0;
- a->_auxBlock.r.right = -1;
- a->_auxBlock.r.top = 0;
- a->_auxBlock.r.bottom = -2;
- break;
- case 30:
- a = derefActor(args[1], "o70_kernelSetFunctions: 30");
- a->_clipOverride.bottom = args[2];
- break;
- case 42:
- _wiz->_rectOverrideEnabled = true;
- _wiz->_rectOverride.left = args[1];
- _wiz->_rectOverride.top = args[2];
- _wiz->_rectOverride.right = args[3];
- _wiz->_rectOverride.bottom = args[4];
- break;
- case 43:
- _wiz->_rectOverrideEnabled = false;
- break;
- default:
- error("o70_kernelSetFunctions: default case %d (param count %d)", args[0], num);
- }
-}
-
-void ScummEngine_v70he::o70_getStringLen() {
- int id, len;
- byte *addr;
-
- id = pop();
-
- addr = getStringAddress(id);
- if (!addr)
- error("o70_getStringLen: Reference to zeroed array pointer (%d)", id);
-
- len = resStrLen(getStringAddress(id));
- push(len);
-}
-
-void ScummEngine_v70he::o70_appendString() {
- int dst, size;
-
- int len = pop();
- int srcOffs = pop();
- int src = pop();
-
- size = len - srcOffs + 2;
- dst = setupStringArray(size);
-
- appendSubstring(dst, src, srcOffs, len);
-
- push(dst);
-}
-
-void ScummEngine_v70he::o70_concatString() {
- int dst, size;
-
- int src2 = pop();
- int src1 = pop();
-
- size = resStrLen(getStringAddress(src1));
- size += resStrLen(getStringAddress(src2)) + 1;
- dst = setupStringArray(size);
-
- appendSubstring(dst, src1, 0, -1);
- appendSubstring(dst, src2, 0, -1);
-
- push(dst);
-}
-
-void ScummEngine_v70he::o70_compareString() {
- int result;
-
- int array1 = pop();
- int array2 = pop();
-
- byte *string1 = getStringAddress(array1);
- if (!string1)
- error("o70_compareString: Reference to zeroed array pointer (%d)", array1);
-
- byte *string2 = getStringAddress(array2);
- if (!string2)
- error("o70_compareString: Reference to zeroed array pointer (%d)", array2);
-
- while (*string1 == *string2) {
- if (*string2 == 0) {
- push(0);
- return;
- }
-
- string1++;
- string2++;
- }
-
- result = (*string1 > *string2) ? -1 : 1;
- push(result);
-}
-
-void ScummEngine_v70he::o70_isResourceLoaded() {
- // Reports percentage of resource loaded by queue
- int type;
-
- byte subOp = fetchScriptByte();
- /* int idx = */ pop();
-
- switch (subOp) {
- case 18:
- type = rtImage;
- break;
- case 226:
- type = rtRoom;
- break;
- case 227:
- type = rtCostume;
- break;
- case 228:
- type = rtSound;
- break;
- case 229:
- type = rtScript;
- break;
- default:
- error("o70_isResourceLoaded: default case %d", subOp);
- }
-
- push(100);
-}
-
-void ScummEngine_v70he::o70_readINI() {
- byte option[256];
- ArrayHeader *ah;
- const char *entry;
- int len, type;
-
- convertMessageToString(_scriptPointer, option, sizeof(option));
- len = resStrLen(_scriptPointer);
- _scriptPointer += len + 1;
-
- type = pop();
- switch (type) {
- case 1: // number
- if (!strcmp((char *)option, "NoPrinting")) {
- push(1);
- } else if (!strcmp((char *)option, "TextOn")) {
- push(ConfMan.getBool("subtitles"));
- } else {
- push(ConfMan.getInt((char *)option));
- }
- break;
- case 2: // string
- entry = (ConfMan.get((char *)option).c_str());
-
- writeVar(0, 0);
- len = resStrLen((const byte *)entry);
- ah = defineArray(0, kStringArray, 0, len);
- memcpy(ah->data, entry, len);
-
- push(readVar(0));
- break;
- default:
- error("o70_readINI: default type %d", type);
- }
- debug(1, "o70_readINI: Option %s", option);
-}
-
-void ScummEngine_v70he::o70_writeINI() {
- int type, value;
- byte option[256], string[256];
- int len;
-
- type = pop();
- value = pop();
-
- convertMessageToString(_scriptPointer, option, sizeof(option));
- len = resStrLen(_scriptPointer);
- _scriptPointer += len + 1;
-
- switch (type) {
- case 1: // number
- ConfMan.set((char *)option, value);
- debug(1, "o70_writeINI: Option %s Value %d", option, value);
- break;
- case 2: // string
- convertMessageToString(_scriptPointer, string, sizeof(string));
- len = resStrLen(_scriptPointer);
- _scriptPointer += len + 1;
- ConfMan.set((char *)option, (char *)string);
- debug(1, "o70_writeINI: Option %s String %s", option, string);
- break;
- default:
- error("o70_writeINI: default type %d", type);
- }
-}
-
-void ScummEngine_v70he::o70_getStringLenForWidth() {
- int chr, max;
- int array, len, pos, width = 0;
-
- max = pop();
- pos = pop();
- array = pop();
-
- len = resStrLen(getStringAddress(array));
-
- writeVar(0, array);
- while (pos <= len) {
- chr = readArray(0, 0, pos);
- width += getStringCharWidth(chr);
- if (width >= max) {
- push(pos);
- return;
- }
- pos++;
- }
-
- push(len);
-}
-
-void ScummEngine_v70he::o70_getCharIndexInString() {
- int array, end, len, pos, value;
-
- value = pop();
- end = pop();
- pos = pop();
- array = pop();
-
- if (end >= 0) {
- len = resStrLen(getStringAddress(array));
- if (len < end)
- end = len;
- } else {
- end = 0;
- }
-
- if (pos < 0)
- pos = 0;
-
- writeVar(0, array);
- if (end > pos) {
- while (end >= pos) {
- if (readArray(0, 0, pos) == value) {
- push(pos);
- return;
- }
- pos++;
- }
- } else {
- while (end <= pos) {
- if (readArray(0, 0, pos) == value) {
- push(pos);
- return;
- }
- pos--;
- }
- }
-
- push(-1);
-}
-
-void ScummEngine_v70he::o70_setFilePath() {
- int len;
- byte filename[100];
-
- convertMessageToString(_scriptPointer, filename, sizeof(filename));
- len = resStrLen(_scriptPointer);
- _scriptPointer += len + 1;
-
- debug(1,"stub o70_setFilePath(%s)", filename);
-}
-
-void ScummEngine_v70he::o70_setSystemMessage() {
- int len;
- byte name[255];
-
- byte subOp = fetchScriptByte();
-
- convertMessageToString(_scriptPointer, name, sizeof(name));
- len = resStrLen(_scriptPointer);
- _scriptPointer += len + 1;
-
- switch (subOp) {
- case 240:
- debug(1,"o70_setSystemMessage: (%d) %s", subOp, name);
- break;
- case 241: // Set Version
- debug(1,"o70_setSystemMessage: (%d) %s", subOp, name);
- break;
- case 242:
- debug(1,"o70_setSystemMessage: (%d) %s", subOp, name);
- break;
- case 243: // Set Window Caption
- _system->setWindowCaption((const char *)name);
- break;
- default:
- error("o70_setSystemMessage: default case %d", subOp);
- }
-}
-
-void ScummEngine_v70he::o70_polygonOps() {
- int vert1x, vert1y, vert2x, vert2y, vert3x, vert3y, vert4x, vert4y;
- int id, fromId, toId;
- bool flag;
-
- byte subOp = fetchScriptByte();
-
- switch (subOp) {
- case 68: // HE 100
- case 69: // HE 100
- case 246:
- case 248:
- vert4y = pop();
- vert4x = pop();
- vert3y = pop();
- vert3x = pop();
- vert2y = pop();
- vert2x = pop();
- vert1y = pop();
- vert1x = pop();
- flag = (subOp == 69 || subOp == 248);
- id = pop();
- _wiz->polygonStore(id, flag, vert1x, vert1y, vert2x, vert2y, vert3x, vert3y, vert4x, vert4y);
- break;
- case 28: // HE 100
- case 247:
- toId = pop();
- fromId = pop();
- _wiz->polygonErase(fromId, toId);
- break;
- default:
- error("o70_polygonOps: default case %d", subOp);
- }
-}
-
-void ScummEngine_v70he::o70_polygonHit() {
- int y = pop();
- int x = pop();
- push(_wiz->polygonHit(0, x, y));
-}
-
-} // End of namespace Scumm
Modified: scummvm/trunk/engines/scumm/he/script_v80he.cpp
===================================================================
--- scummvm/trunk/engines/scumm/he/script_v80he.cpp 2006-02-15 18:48:56 UTC (rev 20702)
+++ scummvm/trunk/engines/scumm/he/script_v80he.cpp 2006-02-15 18:48:49 UTC (rev 20703)
@@ -32,7 +32,7 @@
#include "scumm/he/intern_he.h"
#include "scumm/object.h"
#include "scumm/resource.h"
-#include "scumm/he/resource_v7he.h"
+#include "scumm/he/resource_he.h"
#include "scumm/scumm.h"
#include "scumm/sound.h"
#include "scumm/util.h"
Modified: scummvm/trunk/engines/scumm/he/script_v90he.cpp
===================================================================
--- scummvm/trunk/engines/scumm/he/script_v90he.cpp 2006-02-15 18:48:56 UTC (rev 20702)
+++ scummvm/trunk/engines/scumm/he/script_v90he.cpp 2006-02-15 18:48:49 UTC (rev 20703)
@@ -29,7 +29,7 @@
#include "scumm/he/logic_he.h"
#include "scumm/object.h"
#include "scumm/resource.h"
-#include "scumm/he/resource_v7he.h"
+#include "scumm/he/resource_he.h"
#include "scumm/scumm.h"
#include "scumm/sound.h"
#include "scumm/he/sprite_he.h"
Modified: scummvm/trunk/engines/scumm/module.mk
===================================================================
--- scummvm/trunk/engines/scumm/module.mk 2006-02-15 18:48:56 UTC (rev 20702)
+++ scummvm/trunk/engines/scumm/module.mk 2006-02-15 18:48:49 UTC (rev 20703)
@@ -39,7 +39,7 @@
script_v2.o \
script_v5.o \
script_v6.o \
- he/script_v6he.o \
+ he/script_v60he.o \
scumm.o \
sound.o \
he/sound_he.o \
@@ -83,8 +83,8 @@
he/floodfill_he.o \
he/logic_he.o \
he/palette_he.o \
- he/resource_v7he.o \
- he/script_v7he.o \
+ he/resource_he.o \
+ he/script_v70he.o \
he/script_v72he.o \
he/script_v80he.o \
he/script_v90he.o \
Modified: scummvm/trunk/engines/scumm/scumm.cpp
===================================================================
--- scummvm/trunk/engines/scumm/scumm.cpp 2006-02-15 18:48:56 UTC (rev 20702)
+++ scummvm/trunk/engines/scumm/scumm.cpp 2006-02-15 18:48:49 UTC (rev 20703)
@@ -51,7 +51,7 @@
#include "scumm/player_v2.h"
#include "scumm/player_v2a.h"
#include "scumm/player_v3a.h"
-#include "scumm/he/resource_v7he.h"
+#include "scumm/he/resource_he.h"
#include "scumm/scumm.h"
#include "scumm/sound.h"
#include "scumm/he/sprite_he.h"
More information about the Scummvm-git-logs
mailing list