From 3a3fd9f009e253b9943dcbc56324a0c935324d04 Mon Sep 17 00:00:00 2001 From: Matthew Hoops Date: Tue, 22 Feb 2011 11:19:47 -0500 Subject: SCUMM: Use the new PEResources class for HE cursors Putt-Putt Saves the Zoo HE72 still works fine for me --- engines/scumm/he/resource_he.cpp | 1038 ++++---------------------------------- engines/scumm/he/resource_he.h | 310 +----------- 2 files changed, 99 insertions(+), 1249 deletions(-) (limited to 'engines') diff --git a/engines/scumm/he/resource_he.cpp b/engines/scumm/he/resource_he.cpp index 72e7052034..987ee1ebe3 100644 --- a/engines/scumm/he/resource_he.cpp +++ b/engines/scumm/he/resource_he.cpp @@ -4,7 +4,7 @@ * are too numerous to list here. Please refer to the COPYRIGHT * file distributed with this source distribution. * - * Parts of this code are heavily based on: + * Parts of this code are based on: * icoutils - A set of programs dealing with MS Windows icons and cursors. * Copyright (C) 1998-2001 Oskar Liljeblad * @@ -43,14 +43,6 @@ namespace Scumm { -#if defined(SCUMM_LITTLE_ENDIAN) -#define LE16(x) -#define LE32(x) -#elif defined(SCUMM_BIG_ENDIAN) -#define LE16(x) ((x) = TO_LE_16(x)) -#define LE32(x) ((x) = TO_LE_32(x)) -#endif - ResExtractor::ResExtractor(ScummEngine_v70he *scumm) : _vm(scumm) { @@ -126,912 +118,134 @@ void ResExtractor::setCursor(int id) { } -/* - * 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 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 = NULL; - if (_fileName.empty()) { // We are running for the first time _fileName = _vm->generateFilename(-3); - } - - /* get file size */ - fi.file = SearchMan.createReadStreamForMember(_fileName); - if (!fi.file) { - error("Cannot open file %s", _fileName.c_str()); - } - - fi.total_size = fi.file->size(); - if (fi.total_size == -1) { - error("Cannot get size of file %s", _fileName.c_str()); - goto cleanup; - } - if (fi.total_size == 0) { - error("%s: file has a size of 0", _fileName.c_str()); - 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", _fileName.c_str()); - goto cleanup; - } - - /* identify file and find resource table */ - if (!read_library(&fi)) { - /* error reported by read_library */ - goto cleanup; - } - - /* errors will be printed by the callback */ - ressize = do_resources(&fi, arg_type, arg_name, arg_language, data); - - /* free stuff and close file */ - cleanup: - delete fi.file; - free(fi.memory); - - return ressize; -} - - -/** - * 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; -} - -/** - * 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; -} - -/** - * Return the resource id quoted if it is a string, otherwise (i.e. if - * it is numeric) just return it. - */ -Common::String Win32ResExtractor::WinResource::getQuotedResourceId() const { - if (numeric_id || id[0] == '\0') - return id; - return '"' + Common::String(id) + '"'; -} - -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); - - if (lang_wr != NULL && lang_wr->id[0] != '\0') { - debugC(DEBUG_RESOURCE, "extractCursor(). Found cursor name: %s language: %s [size=%d]", - name_wr->getQuotedResourceId().c_str(), lang_wr->getQuotedResourceId().c_str(), size); - } else { - debugC(DEBUG_RESOURCE, "extractCursor(). Found cursor name: %s [size=%d]", - name_wr->getQuotedResourceId().c_str(), size); - } - return size; -} - -/** - * 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; -} - -/** - * 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 < FROM_LE_16(icondir->count); c++) { - int level; - int iconsize; - char name[14]; - WinResource *fwr; - - RETURN_IF_BAD_POINTER(NULL, icondir->entries[c]); - /*debug("%d. bytes_in_res=%d width=%d height=%d planes=%d bit_count=%d", c, - FROM_LE_32(icondir->entries[c].bytes_in_res), - (is_icon ? icondir->entries[c].res_info.icon.width : FROM_LE_16(icondir->entries[c].res_info.cursor.width)), - (is_icon ? icondir->entries[c].res_info.icon.height : FROM_LE_16(icondir->entries[c].res_info.cursor.height)), - FROM_LE_16(icondir->entries[c].plane_count), - FROM_LE_16(icondir->entries[c].bit_count));*/ - - /* find the corresponding icon resource */ - snprintf(name, sizeof(name)/sizeof(char), "-%d", FROM_LE_16(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.", - _fileName.c_str(), &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", _fileName.c_str(), name); - skipped++; - continue; - } - if ((uint32)iconsize != FROM_LE_32(icondir->entries[c].bytes_in_res)) { - debugC(DEBUG_RESOURCE, "%s: mismatch of size in icon resource `%s' and group (%d != %d)", - _fileName.c_str(), name, iconsize, FROM_LE_32(icondir->entries[c].bytes_in_res)); - } - size += iconsize; /* size += FROM_LE_32(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) + (FROM_LE_16(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 = TO_LE_16(FROM_LE_16(icondir->count) - skipped); - - /* transfer each cursor/icon: Win32CursorIconDirEntry and data */ - skipped = 0; - for (c = 0; c < FROM_LE_16(icondir->count); c++) { - int level; - char name[14]; - WinResource *fwr; - byte *data; - - /* find the corresponding icon resource */ - snprintf(name, sizeof(name)/sizeof(char), "-%d", FROM_LE_16(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.", - _fileName.c_str(), &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 = TO_LE_16(FROM_LE_16(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 = TO_LE_32(offset); - - /* transfer resource into file memory */ - if (is_icon) { - memcpy(&memory[offset], data, FROM_LE_32(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, - FROM_LE_32(icondir->entries[c].bytes_in_res)-sizeof(uint16)*2); - offset -= sizeof(uint16)*2; - } - - /* increase the offset pointer */ - offset += FROM_LE_32(icondir->entries[c].bytes_in_res); + if (!_exe.loadFromEXE(_fileName)) + error("Cannot open file %s", _fileName.c_str()); } - return memory; -} - -/** - * 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, (uint)((byte *)offset - memory), size); + Common::SeekableReadStream *cursorGroup = _exe.getResource(Common::kPEGroupCursor, resId); - if (need_size < 0 || need_size > total_size) { - error("%s: premature end", name); - return false; - } + if (!cursorGroup) + error("Could not find cursor group %d", resId); - return true; -} + cursorGroup->skip(4); + uint16 count = cursorGroup->readUint16LE(); + assert(count > 0); + cursorGroup->skip(12); + resId = cursorGroup->readUint16LE(); -/** - * Do something for each resource matching type, name and lang. - */ -int Win32ResExtractor::do_resources(WinLibrary *fi, const char *type, char *name, char *lang, byte **data) { - WinResource *type_wr; - WinResource *name_wr; - WinResource *lang_wr; - int size; + delete cursorGroup; - type_wr = (WinResource *)calloc(3, sizeof(WinResource)); - name_wr = type_wr + 1; - lang_wr = type_wr + 2; + Common::SeekableReadStream *cursor = _exe.getResource(Common::kPECursor, resId); - size = do_resources_recurs(fi, NULL, type_wr, name_wr, lang_wr, type, name, lang, data); + if (!cursor) + error("Could not find cursor %d", resId); - free(type_wr); + int size = cursor->size(); + *data = (byte *)malloc(size); + cursor->read(*data, size); + delete cursor; 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, 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) { - return size; - } - - /* 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, 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; -} - -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++; - cmp1 = strtol(wr->id, 0, 10); - cmp2 = strtol(id, 0, 10); - if (!cmp1 || !cmp2 || 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 = FROM_LE_16(mem[0]); - RETURN_IF_BAD_OFFSET(false, &mem[1], sizeof(uint16) * len); - - len = MIN(FROM_LE_16(mem[0]), (uint16)WINRES_ID_MAXLEN); - for (c = 0; c < len; c++) - wr->id[c] = FROM_LE_16(mem[c+1]) & 0x00FF; - wr->id[len] = '\0'; - wr->numeric_id = false; - } else { /* Unicode string id */ - /* translate id into a string */ - snprintf(wr->id, WINRES_ID_MAXLEN, "%d", value); - wr->numeric_id = true; - } - - return true; -} - -byte *Win32ResExtractor::get_resource_entry(WinLibrary *fi, WinResource *wr, int *size) { - byte *result; - - Win32ImageResourceDataEntry *dataent; - - dataent = (Win32ImageResourceDataEntry *) wr->children; - RETURN_IF_BAD_POINTER(NULL, *dataent); - *size = FROM_LE_32(dataent->size); - - result = fi->memory + FROM_LE_32(dataent->offset_to_data); - - RETURN_IF_BAD_OFFSET(NULL, result, *size); - - return result; -} - -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 = FROM_LE_16(pe_res->number_of_named_entries) + FROM_LE_16(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 = ((FROM_LE_32(dirent[c].offset_to_data) & IMAGE_RESOURCE_DATA_IS_DIRECTORY) != 0); - wr[c].children = fi->first_resource + (FROM_LE_32(dirent[c].offset_to_data) & ~IMAGE_RESOURCE_DATA_IS_DIRECTORY); - - /* fill in wr->id, wr->numeric_id */ - if (!decode_pe_resource_id(fi, wr + c, FROM_LE_32(dirent[c].name))) { - free(wr); - return NULL; - } - } - - return wr; -} - - -/** - * 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; - - return list_pe_resources(fi, (Win32ImageResourceDirectory *) - (res == NULL ? fi->first_resource : res->children), - (res == NULL ? 0 : res->level+1), - count); -} - -/** - * 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 (FROM_LE_16(MZ_HEADER(fi->memory)->magic) == IMAGE_DOS_SIGNATURE) { - DOSImageHeader *mz_header = MZ_HEADER(fi->memory); - - RETURN_IF_BAD_POINTER(false, mz_header->lfanew); - - // Apply endian fix (currently only lfanew is used from the DOSImageHeader, - // so we don't bother to 'fix' the rest). - LE32(mz_header->lfanew); - - if (mz_header->lfanew < sizeof(DOSImageHeader)) { - error("%s: not a Windows library", _fileName.c_str()); - return false; - } - } - - /* check for NT header signature `PE' */ - RETURN_IF_BAD_POINTER(false, PE_HEADER(fi->memory)->signature); - if (FROM_LE_32(PE_HEADER(fi->memory)->signature) == IMAGE_NT_SIGNATURE) { - Win32ImageNTHeaders *pe_header; - int d; +#define ROW_BYTES(bits) ((((bits) + 31) >> 5) << 2) - // Fix image header endianess - fix_win32_image_header_endian(PE_HEADER(fi->memory)); +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) { - /* allocate new memory */ - fi->total_size = calc_vma_size(fi); - if (fi->total_size == 0) { - /* calc_vma_size has reported error */ - return false; - } - byte *ptr = (byte *)realloc(fi->memory, fi->total_size); - assert(ptr); - fi->memory = ptr; - - /* 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--) { - Win32ImageSectionHeader *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 (FROM_LE_32(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); - } - } + Common::MemoryReadStream *in = new Common::MemoryReadStream(data, datasize); - /* find resource directory */ - RETURN_IF_BAD_POINTER(false, pe_header->optional_header.data_directory[IMAGE_DIRECTORY_ENTRY_RESOURCE]); - Win32ImageDataDirectory *dir = pe_header->optional_header.data_directory + IMAGE_DIRECTORY_ENTRY_RESOURCE; - if (dir->size == 0) { - error("%s: file contains no resources", _fileName.c_str()); - return false; - } + *hotspot_x = in->readUint16LE(); + *hotspot_y = in->readUint16LE(); - fix_win32_image_data_directory(dir); + Win32BitmapInfoHeader bitmap; - fi->first_resource = fi->memory + dir->virtual_address; - return true; - } + in->read(&bitmap, sizeof(Win32BitmapInfoHeader)); - /* other (unknown) header signature was found */ - error("%s: not a Windows library", _fileName.c_str()); - return false; -} + fix_win32_bitmap_info_header_endian(&bitmap); + if (bitmap.size < sizeof(Win32BitmapInfoHeader)) + error("bitmap header is too short"); -/** - * 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); - fix_win32_image_section_header(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++; - } + if (bitmap.compression != 0) + error("compressed image data not supported"); - return size; -} + if (bitmap.x_pels_per_meter != 0) + error("x_pels_per_meter field in bitmap should be zero"); -Win32ResExtractor::WinResource *Win32ResExtractor::find_with_resource_array(WinLibrary *fi, WinResource *wr, const char *id) { - int c, rescnt; - WinResource *return_wr; + if (bitmap.y_pels_per_meter != 0) + error("y_pels_per_meter field in bitmap should be zero"); - wr = list_resources(fi, wr, &rescnt); - if (wr == NULL) - return NULL; + if (bitmap.clr_important != 0) + error("clr_important field in bitmap should be zero"); - 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)); + if (bitmap.planes != 1) + error("planes field in bitmap should be one"); - /* free old WinResource */ - free(wr); - return return_wr; - } + Win32RGBQuad *palette = NULL; + uint32 palette_count = 0; + 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); + in->read(palette, sizeof(Win32RGBQuad) * palette_count); } - return NULL; -} + uint32 width = bitmap.width; + uint32 height = ABS(bitmap.height) / 2; -Win32ResExtractor::WinResource *Win32ResExtractor::find_resource(WinLibrary *fi, const char *type, const char *name, const char *language, int *level) { - WinResource *wr; + uint32 image_size = height * ROW_BYTES(width * bitmap.bit_count); + uint32 mask_size = height * ROW_BYTES(width); - *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; - Common::MemoryReadStream *in = new Common::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; - } + byte *image_data = (byte *)malloc(image_size); + in->read(image_data, image_size); - 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"); - } + byte *mask_data = (byte *)malloc(mask_size); + in->read(mask_data, mask_size); - 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, - (int)(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); - - // We set up cursor palette for default cursor, so use it - if (!simple_vec(mask_data, x + mmod, 1)) { - if (color) { - cursor[0][width * d + x] = 254; // white - } else { - cursor[0][width * d + x] = 253; // black - } - } 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; - */ - } - - } - - free(row); - free(palette); - if (image_data != NULL) { - free(image_data); - free(mask_data); - } - continue; - - local_cleanup: - - free(row); - free(palette); - if (image_data != NULL) { - free(image_data); - free(mask_data); - } - goto cleanup; + + *w = width; + *h = height; + *keycolor = 0; + *cursor = (byte *)malloc(width * height); + + byte *row = (byte *)malloc(width * 4); + + for (uint32 d = 0; d < height; d++) { + 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 (uint32 x = 0; x < width; x++) { + uint32 color = simple_vec(image_data, x + imod, bitmap.bit_count); + + // HACK: Ignore the actual cursor palette and use SCUMM's + if (!simple_vec(mask_data, x + mmod, 1)) { + if (color) + cursor[0][width * d + x] = 254; // white + else + cursor[0][width * d + x] = 253; // black } else { - if (entries[c].dib_offset > offset) - min_offset = MIN(min_offset, entries[c].dib_offset); + cursor[0][width * d + x] = 255; // transparent } } - if (previous == completed) { - if (min_offset < offset) { - error("offset of bitmap header incorrect (too low)"); - goto cleanup; - } - assert(min_offset != 0x7fffffff); - 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(row); + free(palette); + if (image_data != NULL) { + free(image_data); + free(mask_data); + } - free(entries); - return -1; + return 1; } uint32 Win32ResExtractor::simple_vec(byte *data, uint32 ofs, byte size) { @@ -1055,11 +269,13 @@ uint32 Win32ResExtractor::simple_vec(byte *data, uint32 ofs, byte size) { return 0; } -void Win32ResExtractor::fix_win32_cursor_icon_file_dir_endian(Win32CursorIconFileDir *obj) { - LE16(obj->reserved); - LE16(obj->type); - LE16(obj->count); -} +#if defined(SCUMM_LITTLE_ENDIAN) +#define LE16(x) +#define LE32(x) +#elif defined(SCUMM_BIG_ENDIAN) +#define LE16(x) ((x) = TO_LE_16(x)) +#define LE32(x) ((x) = TO_LE_32(x)) +#endif void Win32ResExtractor::fix_win32_bitmap_info_header_endian(Win32BitmapInfoHeader *obj) { LE32(obj->size); @@ -1075,76 +291,8 @@ void Win32ResExtractor::fix_win32_bitmap_info_header_endian(Win32BitmapInfoHeade 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); -} - -/* 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); - - // FIXME: Does this assert ever trigger? If so, we should modify this function - // to properly deal with it. - assert(obj->file_header.size_of_optional_header >= sizeof(obj->optional_header)); - 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); -} - +#undef LE16 +#undef LE32 MacResExtractor::MacResExtractor(ScummEngine_v70he *scumm) : ResExtractor(scumm) { _resMgr = NULL; diff --git a/engines/scumm/he/resource_he.h b/engines/scumm/he/resource_he.h index 6b4c3fe493..9dddc96f23 100644 --- a/engines/scumm/he/resource_he.h +++ b/engines/scumm/he/resource_he.h @@ -4,7 +4,7 @@ * are too numerous to list here. Please refer to the COPYRIGHT * file distributed with this source distribution. * - * Parts of this code are heavily based on: + * Parts of this code are based on: * icoutils - A set of programs dealing with MS Windows icons and cursors. * Copyright (C) 1998-2001 Oskar Liljeblad * @@ -31,89 +31,10 @@ #define SCUMM_HE_RESOURCE_HE_H #include "common/macresman.h" +#include "common/pe_exe.h" namespace Scumm { -#define WINRES_ID_MAXLEN (256) - -/* - * Definitions - */ - -#define MZ_HEADER(x) ((DOSImageHeader *)(x)) - -#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_NT_SIGNATURE 0x00004550 /* PE00 */ - -/* The following symbols below and another group a few lines below are defined in - * the windows header, at least in wince and most likely in plain win32 as well. - * Defining them out silences a redefinition warning in gcc. - * If the same problem arises in win32 builds as well, please replace - * _WIN32_WCE with _WIN32 which is also defined in the wince platform. - */ -#ifndef _WIN32_WCE -#define IMAGE_SCN_CNT_CODE 0x00000020 -#define IMAGE_SCN_CNT_INITIALIZED_DATA 0x00000040 -#define IMAGE_SCN_CNT_UNINITIALIZED_DATA 0x00000080 -#endif - -// Only IMAGE_DIRECTORY_ENTRY_RESOURCE is used: -#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 - -#ifndef _WIN32_WCE -// Only RT_GROUP_CURSOR and RT_GROUP_ICON are used -#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, _fileName.c_str(), &(x), sizeof(x))) \ - return (r); -#define RETURN_IF_BAD_OFFSET(r, x, s) \ - if (!check_offset(fi->memory, fi->total_size, _fileName.c_str(), x, s)) \ - return (r); - class ScummEngine_v70he; class ResExtractor { @@ -154,7 +75,7 @@ public: }; class Win32ResExtractor : public ResExtractor { - public: +public: Win32ResExtractor(ScummEngine_v70he *scumm); ~Win32ResExtractor() {} int extractResource(int id, byte **data); @@ -162,81 +83,15 @@ class Win32ResExtractor : public ResExtractor { 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); +private: + Common::PEResources _exe; + /* * Structures */ #include "common/pack-start.h" // START STRUCT PACKING - struct WinLibrary { - Common::SeekableReadStream *file; - byte *memory; - byte *first_resource; - int total_size; - } PACKED_STRUCT; - - struct WinResource { - char id[256]; - void *this_; - void *children; - int level; - bool numeric_id; - bool is_directory; - - Common::String getQuotedResourceId() const; - } PACKED_STRUCT; - - - struct Win32IconResDir { - byte width; - byte height; - byte color_count; - byte reserved; - } PACKED_STRUCT; - - struct Win32CursorDir { - uint16 width; - uint16 height; - } PACKED_STRUCT; - - struct Win32CursorIconDirEntry { - union { - Win32IconResDir icon; - Win32CursorDir cursor; - } res_info; - uint16 plane_count; - uint16 bit_count; - uint32 bytes_in_res; - uint16 res_id; - } PACKED_STRUCT; - - struct Win32CursorIconDir { - uint16 reserved; - uint16 type; - uint16 count; - Win32CursorIconDirEntry entries[1]; - } PACKED_STRUCT; - - struct Win32CursorIconFileDirEntry { - byte width; - byte height; - byte color_count; - byte reserved; - uint16 hotspot_x; - uint16 hotspot_y; - uint32 dib_size; - uint32 dib_offset; - } PACKED_STRUCT; - - struct Win32CursorIconFileDir { - uint16 reserved; - uint16 type; - uint16 count; - Win32CursorIconFileDirEntry entries[1]; - } PACKED_STRUCT; - struct Win32BitmapInfoHeader { uint32 size; int32 width; @@ -258,163 +113,10 @@ class Win32ResExtractor : public ResExtractor { byte reserved; } PACKED_STRUCT; - struct Win32ImageResourceDirectoryEntry { - uint32 name; - uint32 offset_to_data; - } PACKED_STRUCT; - - struct Win16NETypeInfo { - uint16 type_id; - uint16 count; - uint32 resloader; // FARPROC16 - smaller? uint16? - } PACKED_STRUCT; - - 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; - } PACKED_STRUCT; - - 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; - } PACKED_STRUCT; - - struct Win32ImageDataDirectory { - uint32 virtual_address; - uint32 size; - } PACKED_STRUCT; - - 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]; - } PACKED_STRUCT; - - struct Win32ImageNTHeaders { - uint32 signature; - Win32ImageFileHeader file_header; - Win32ImageOptionalHeader optional_header; - } PACKED_STRUCT; - - 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; - } PACKED_STRUCT; - - struct Win32ImageResourceDataEntry { - uint32 offset_to_data; - uint32 size; - uint32 code_page; - uint32 resource_handle; - } PACKED_STRUCT; - - struct Win32ImageResourceDirectory { - uint32 characteristics; - uint32 time_date_stamp; - uint16 major_version; - uint16 minor_version; - uint16 number_of_named_entries; - uint16 number_of_id_entries; - } PACKED_STRUCT; - #include "common/pack-end.h" // END STRUCT PACKING -/* - * 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 *, 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); - 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 *, byte **); - 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_win32_image_header_endian(Win32ImageNTHeaders *obj); - void fix_win32_image_data_directory(Win32ImageDataDirectory *obj); }; class MacResExtractor : public ResExtractor { -- cgit v1.2.3 From a2a0b13de2cd6fb28787b2821466f3ef7c2210ea Mon Sep 17 00:00:00 2001 From: Matthew Hoops Date: Tue, 22 Feb 2011 20:01:19 -0500 Subject: COMMON: Begin to merge some NE/PE code The ID classes are now common to both. The files have been renamed to better illustrate their purpose. --- engines/mohawk/cursors.cpp | 2 +- engines/scumm/he/resource_he.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'engines') diff --git a/engines/mohawk/cursors.cpp b/engines/mohawk/cursors.cpp index eb11eb175e..ebc8d1ea8a 100644 --- a/engines/mohawk/cursors.cpp +++ b/engines/mohawk/cursors.cpp @@ -31,8 +31,8 @@ #include "mohawk/riven_cursors.h" #include "common/macresman.h" -#include "common/ne_exe.h" #include "common/system.h" +#include "common/winexe_ne.h" #include "graphics/cursorman.h" namespace Mohawk { diff --git a/engines/scumm/he/resource_he.h b/engines/scumm/he/resource_he.h index 9dddc96f23..f81dd713f1 100644 --- a/engines/scumm/he/resource_he.h +++ b/engines/scumm/he/resource_he.h @@ -31,7 +31,7 @@ #define SCUMM_HE_RESOURCE_HE_H #include "common/macresman.h" -#include "common/pe_exe.h" +#include "common/winexe_pe.h" namespace Scumm { -- cgit v1.2.3 From e053373dd344b96e9c29128b97196b3d7f9d2e75 Mon Sep 17 00:00:00 2001 From: Matthew Hoops Date: Tue, 22 Feb 2011 20:11:50 -0500 Subject: COMMON: Add a key color field to NECursor --- engines/mohawk/cursors.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'engines') diff --git a/engines/mohawk/cursors.cpp b/engines/mohawk/cursors.cpp index ebc8d1ea8a..cdfdbb3a78 100644 --- a/engines/mohawk/cursors.cpp +++ b/engines/mohawk/cursors.cpp @@ -301,7 +301,7 @@ void NECursorManager::setCursor(uint16 id) { for (uint32 i = 0; i < cursors.size(); i++) { if (cursors[i].id == id) { Common::NECursor *cursor = cursors[i].cursors[0]; - CursorMan.replaceCursor(cursor->getSurface(), cursor->getWidth(), cursor->getHeight(), cursor->getHotspotX(), cursor->getHotspotY(), 0); + CursorMan.replaceCursor(cursor->getSurface(), cursor->getWidth(), cursor->getHeight(), cursor->getHotspotX(), cursor->getHotspotY(), cursor->getKeyColor()); CursorMan.replaceCursorPalette(cursor->getPalette(), 0, 256); return; } -- cgit v1.2.3 From c66233f83e2d86b72f45aff20fb3198976850e42 Mon Sep 17 00:00:00 2001 From: Matthew Hoops Date: Fri, 4 Mar 2011 23:17:57 -0500 Subject: GRAPHICS: Split the NE cursor code from the NEResources class Now the code lies in Graphics and all cursors are not cached upon opening an exe. The engine is now in charge of caching which cursors it wants. --- engines/mohawk/cursors.cpp | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) (limited to 'engines') diff --git a/engines/mohawk/cursors.cpp b/engines/mohawk/cursors.cpp index cdfdbb3a78..fe4b434f9c 100644 --- a/engines/mohawk/cursors.cpp +++ b/engines/mohawk/cursors.cpp @@ -34,6 +34,7 @@ #include "common/system.h" #include "common/winexe_ne.h" #include "graphics/cursorman.h" +#include "graphics/wincursor.h" namespace Mohawk { @@ -295,16 +296,14 @@ NECursorManager::~NECursorManager() { } void NECursorManager::setCursor(uint16 id) { - if (!_exe) { - Common::Array cursors = _exe->getCursors(); - - for (uint32 i = 0; i < cursors.size(); i++) { - if (cursors[i].id == id) { - Common::NECursor *cursor = cursors[i].cursors[0]; - CursorMan.replaceCursor(cursor->getSurface(), cursor->getWidth(), cursor->getHeight(), cursor->getHotspotX(), cursor->getHotspotY(), cursor->getKeyColor()); - CursorMan.replaceCursorPalette(cursor->getPalette(), 0, 256); - return; - } + if (_exe) { + Graphics::WinCursorGroup *cursorGroup = Graphics::WinCursorGroup::createCursorGroup(*_exe, id); + + if (cursorGroup) { + Graphics::WinCursor *cursor = cursorGroup->cursors[0].cursor; + CursorMan.replaceCursor(cursor->getSurface(), cursor->getWidth(), cursor->getHeight(), cursor->getHotspotX(), cursor->getHotspotY(), cursor->getKeyColor()); + CursorMan.replaceCursorPalette(cursor->getPalette(), 0, 256); + return; } } -- cgit v1.2.3 From 6582b77f1c3c6f373d2aa3a55f30c254f5f0e244 Mon Sep 17 00:00:00 2001 From: Matthew Hoops Date: Sun, 6 Mar 2011 19:57:18 -0500 Subject: SCUMM: Use the new WinCursor code in SCUMM HE Also, updated the MacResManager cursor code to reflect the SCUMM resource extractor code changes --- engines/sci/graphics/cursor.cpp | 12 +- engines/scumm/he/resource_he.cpp | 256 +++++++++------------------------------ engines/scumm/he/resource_he.h | 75 +++--------- 3 files changed, 78 insertions(+), 265 deletions(-) (limited to 'engines') diff --git a/engines/sci/graphics/cursor.cpp b/engines/sci/graphics/cursor.cpp index b085654d02..567e02eeb9 100644 --- a/engines/sci/graphics/cursor.cpp +++ b/engines/sci/graphics/cursor.cpp @@ -26,6 +26,7 @@ #include "common/config-manager.h" #include "common/events.h" #include "common/macresman.h" +#include "common/memstream.h" #include "common/system.h" #include "common/util.h" #include "graphics/cursorman.h" @@ -485,8 +486,8 @@ void GfxCursor::kernelSetMacCursor(GuiResourceId viewNum, int loopNum, int celNu cursorBitmap[i * 8 + b] = 0; // Doesn't matter, just is transparent } - uint16 hotspotX = READ_BE_UINT16(data); - uint16 hotspotY = READ_BE_UINT16(data + 2); + uint16 hotspotY = READ_BE_UINT16(data); + uint16 hotspotX = READ_BE_UINT16(data + 2); static const byte cursorPalette[] = { 0x00, 0x00, 0x00, 0xff, 0xff, 0xff }; @@ -498,11 +499,12 @@ void GfxCursor::kernelSetMacCursor(GuiResourceId viewNum, int loopNum, int celNu // Mac crsr cursor byte *cursorBitmap, *palette; int width, height, hotspotX, hotspotY, palSize, keycolor; - Common::MacResManager::convertCrsrCursor(resource->data, resource->size, &cursorBitmap, &width, &height, &hotspotX, &hotspotY, &keycolor, true, &palette, &palSize); + Common::MemoryReadStream resStream(resource->data, resource->size); + Common::MacResManager::convertCrsrCursor(&resStream, &cursorBitmap, width, height, hotspotX, hotspotY, keycolor, true, &palette, palSize); CursorMan.replaceCursor(cursorBitmap, width, height, hotspotX, hotspotY, keycolor); CursorMan.replaceCursorPalette(palette, 0, palSize); - free(cursorBitmap); - free(palette); + delete[] cursorBitmap; + delete[] palette; } kernelShow(); diff --git a/engines/scumm/he/resource_he.cpp b/engines/scumm/he/resource_he.cpp index 987ee1ebe3..9349e70eb9 100644 --- a/engines/scumm/he/resource_he.cpp +++ b/engines/scumm/he/resource_he.cpp @@ -4,10 +4,6 @@ * are too numerous to list here. Please refer to the COPYRIGHT * file distributed with this source distribution. * - * Parts of this code are 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 @@ -36,6 +32,7 @@ #include "audio/decoders/wave.h" #include "graphics/cursorman.h" +#include "graphics/wincursor.h" #include "common/archive.h" #include "common/memstream.h" @@ -57,71 +54,71 @@ ResExtractor::~ResExtractor() { 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; - } - } + for (int i = 0; i < MAX_CACHED_CURSORS; ++i) + if (_cursorCache[i].valid && _cursorCache[i].id == id) + return &_cursorCache[i]; + return NULL; } ResExtractor::CachedCursor *ResExtractor::getCachedCursorSlot() { - uint32 min_last_used = 0; + uint32 minLastUsed = 0; CachedCursor *r = NULL; + for (int i = 0; i < MAX_CACHED_CURSORS; ++i) { CachedCursor *cc = &_cursorCache[i]; - if (!cc->valid) { + 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; - } + + if (minLastUsed == 0 || cc->lastUsed < minLastUsed) { + minLastUsed = cc->lastUsed; + r = cc; } } + assert(r); - free(r->bitmap); - free(r->palette); + delete[] r->bitmap; + delete[] 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 %lu", id, (long)(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); + + if (!extractResource(id, cc)) + error("Could not extract cursor %d", id); + debug(7, "Adding cursor %d to cache slot %lu", id, (long)(cc - _cursorCache)); - free(cursorRes); + cc->valid = true; cc->id = id; - cc->last_used = g_system->getMillis(); + cc->lastUsed = g_system->getMillis(); } if (cc->palette) CursorMan.replaceCursorPalette(cc->palette, 0, cc->palSize); - _vm->setCursorHotspot(cc->hotspot_x, cc->hotspot_y); - _vm->setCursorFromBuffer(cc->bitmap, cc->w, cc->h, cc->w); + _vm->setCursorHotspot(cc->hotspotX, cc->hotspotY); + _vm->setCursorFromBuffer(cc->bitmap, cc->width, cc->height, cc->width); } Win32ResExtractor::Win32ResExtractor(ScummEngine_v70he *scumm) : ResExtractor(scumm) { } -int Win32ResExtractor::extractResource(int resId, byte **data) { +bool Win32ResExtractor::extractResource(int id, CachedCursor *cc) { if (_fileName.empty()) { // We are running for the first time _fileName = _vm->generateFilename(-3); @@ -129,176 +126,40 @@ int Win32ResExtractor::extractResource(int resId, byte **data) { error("Cannot open file %s", _fileName.c_str()); } - Common::SeekableReadStream *cursorGroup = _exe.getResource(Common::kPEGroupCursor, resId); - - if (!cursorGroup) - error("Could not find cursor group %d", resId); - - cursorGroup->skip(4); - uint16 count = cursorGroup->readUint16LE(); - assert(count > 0); - - cursorGroup->skip(12); - resId = cursorGroup->readUint16LE(); - - delete cursorGroup; - - Common::SeekableReadStream *cursor = _exe.getResource(Common::kPECursor, resId); - - if (!cursor) - error("Could not find cursor %d", resId); - - int size = cursor->size(); - *data = (byte *)malloc(size); - cursor->read(*data, size); - delete cursor; - - return size; -} - -#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) { - - Common::MemoryReadStream *in = new Common::MemoryReadStream(data, datasize); - - *hotspot_x = in->readUint16LE(); - *hotspot_y = in->readUint16LE(); + Graphics::WinCursorGroup *group = Graphics::WinCursorGroup::createCursorGroup(_exe, id); - Win32BitmapInfoHeader bitmap; + if (!group) + return false; - in->read(&bitmap, sizeof(Win32BitmapInfoHeader)); + Graphics::WinCursor *cursor = group->cursors[0].cursor; - fix_win32_bitmap_info_header_endian(&bitmap); - if (bitmap.size < sizeof(Win32BitmapInfoHeader)) - error("bitmap header is too short"); + cc->bitmap = new byte[cursor->getWidth() * cursor->getHeight()]; + cc->width = cursor->getWidth(); + cc->height = cursor->getHeight(); + cc->hotspotX = cursor->getHotspotX(); + cc->hotspotY = cursor->getHotspotY(); - if (bitmap.compression != 0) - error("compressed image data not supported"); + // Convert from the paletted format to the SCUMM palette + const byte *srcBitmap = cursor->getSurface(); - 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"); - - Win32RGBQuad *palette = NULL; - uint32 palette_count = 0; - 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); - in->read(palette, sizeof(Win32RGBQuad) * palette_count); - } - - uint32 width = bitmap.width; - uint32 height = ABS(bitmap.height) / 2; - - uint32 image_size = height * ROW_BYTES(width * bitmap.bit_count); - uint32 mask_size = height * ROW_BYTES(width); - - byte *image_data = (byte *)malloc(image_size); - in->read(image_data, image_size); - - byte *mask_data = (byte *)malloc(mask_size); - in->read(mask_data, mask_size); - - - *w = width; - *h = height; - *keycolor = 0; - *cursor = (byte *)malloc(width * height); - - byte *row = (byte *)malloc(width * 4); - - for (uint32 d = 0; d < height; d++) { - 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 (uint32 x = 0; x < width; x++) { - uint32 color = simple_vec(image_data, x + imod, bitmap.bit_count); - - // HACK: Ignore the actual cursor palette and use SCUMM's - if (!simple_vec(mask_data, x + mmod, 1)) { - if (color) - cursor[0][width * d + x] = 254; // white - else - cursor[0][width * d + x] = 253; // black - } else { - cursor[0][width * d + x] = 255; // transparent - } - } - - } - - free(row); - free(palette); - if (image_data != NULL) { - free(image_data); - free(mask_data); - } - - 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; + for (int i = 0; i < cursor->getWidth() * cursor->getHeight(); i++) { + if (srcBitmap[i] == cursor->getKeyColor()) // Transparent + cc->bitmap[i] = 255; + else if (srcBitmap[i] == 0) // Black + cc->bitmap[i] = 253; + else // White + cc->bitmap[i] = 254; } - return 0; + delete group; + return true; } -#if defined(SCUMM_LITTLE_ENDIAN) -#define LE16(x) -#define LE32(x) -#elif defined(SCUMM_BIG_ENDIAN) -#define LE16(x) ((x) = TO_LE_16(x)) -#define LE32(x) ((x) = TO_LE_32(x)) -#endif - -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); -} - -#undef LE16 -#undef LE32 - MacResExtractor::MacResExtractor(ScummEngine_v70he *scumm) : ResExtractor(scumm) { _resMgr = NULL; } -int MacResExtractor::extractResource(int id, byte **buf) { +bool MacResExtractor::extractResource(int id, CachedCursor *cc) { // Create the MacResManager if not created already if (_resMgr == NULL) { _resMgr = new Common::MacResManager(); @@ -306,25 +167,18 @@ int MacResExtractor::extractResource(int id, byte **buf) { error("Cannot open file %s", _fileName.c_str()); } - Common::SeekableReadStream *dataStream = _resMgr->getResource('crsr', 1000 + id); + Common::SeekableReadStream *dataStream = _resMgr->getResource('crsr', id + 1000); if (!dataStream) - error("There is no cursor ID #%d", 1000 + id); - - uint32 size = dataStream->size(); - *buf = (byte *)malloc(size); - dataStream->read(*buf, size); - delete dataStream; + return false; - return size; -} + int keyColor; // HACK: key color is ignored + _resMgr->convertCrsrCursor(dataStream, &cc->bitmap, cc->width, cc->height, cc->hotspotX, cc->hotspotY, + keyColor, _vm->_system->hasFeature(OSystem::kFeatureCursorHasPalette), + &cc->palette, cc->palSize); -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) { - - _resMgr->convertCrsrCursor(data, datasize, cursor, w, h, hotspot_x, hotspot_y, keycolor, - _vm->_system->hasFeature(OSystem::kFeatureCursorHasPalette), palette, palSize); - return 1; + delete dataStream; + return true; } void ScummEngine_v70he::readRoomsOffsets() { diff --git a/engines/scumm/he/resource_he.h b/engines/scumm/he/resource_he.h index f81dd713f1..5d7c70db76 100644 --- a/engines/scumm/he/resource_he.h +++ b/engines/scumm/he/resource_he.h @@ -4,10 +4,6 @@ * are too numerous to list here. Please refer to the COPYRIGHT * file distributed with this source distribution. * - * Parts of this code are 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 @@ -44,33 +40,31 @@ public: 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 - }; - +protected: struct CachedCursor { bool valid; int id; byte *bitmap; - int w, h; - int hotspot_x, hotspot_y; - uint32 last_used; + int width, height; + int hotspotX, hotspotY; + uint32 lastUsed; byte *palette; int palSize; }; + Common::String _fileName; ScummEngine_v70he *_vm; + virtual bool extractResource(int id, CachedCursor *cc) = 0; + +private: + enum { + MAX_CACHED_CURSORS = 10 + }; + ResExtractor::CachedCursor *findCachedCursor(int id); ResExtractor::CachedCursor *getCachedCursorSlot(); - - bool _arg_raw; - Common::String _fileName; + CachedCursor _cursorCache[MAX_CACHED_CURSORS]; }; @@ -78,59 +72,22 @@ 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: Common::PEResources _exe; -/* - * Structures - */ - -#include "common/pack-start.h" // START STRUCT PACKING - - 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; - } PACKED_STRUCT; - - struct Win32RGBQuad { - byte blue; - byte green; - byte red; - byte reserved; - } PACKED_STRUCT; - -#include "common/pack-end.h" // END STRUCT PACKING - - uint32 simple_vec(byte *data, uint32 ofs, byte size); - void fix_win32_bitmap_info_header_endian(Win32BitmapInfoHeader *obj); + bool extractResource(int id, CachedCursor *cc); }; class MacResExtractor : public ResExtractor { - public: MacResExtractor(ScummEngine_v70he *scumm); - ~MacResExtractor() { } + ~MacResExtractor() {} private: Common::MacResManager *_resMgr; - int extractResource(int id, byte **buf); - int convertIcons(byte *data, int datasize, byte **cursor, int *w, int *h, - int *hotspot_x, int *hotspot_y, int *keycolor, byte **palette, int *palSize); + bool extractResource(int id, CachedCursor *cc); }; } // End of namespace Scumm -- cgit v1.2.3 From ad7400524b8e024577169f7dd4cb4d586ee37fa0 Mon Sep 17 00:00:00 2001 From: Matthew Hoops Date: Mon, 7 Mar 2011 01:07:53 -0500 Subject: MOHAWK: Make Riven use original executables for cursors It will try both Windows and Macintosh executables. The hardcoded cursors have been removed. --- engines/mohawk/cursors.cpp | 201 ++++-------- engines/mohawk/cursors.h | 34 +- engines/mohawk/riven.cpp | 13 +- engines/mohawk/riven_cursors.h | 670 -------------------------------------- engines/mohawk/riven_external.cpp | 38 ++- engines/mohawk/riven_scripts.cpp | 1 + 6 files changed, 120 insertions(+), 837 deletions(-) delete mode 100644 engines/mohawk/riven_cursors.h (limited to 'engines') diff --git a/engines/mohawk/cursors.cpp b/engines/mohawk/cursors.cpp index fe4b434f9c..fdf19b624a 100644 --- a/engines/mohawk/cursors.cpp +++ b/engines/mohawk/cursors.cpp @@ -28,11 +28,11 @@ #include "mohawk/resource.h" #include "mohawk/graphics.h" #include "mohawk/myst.h" -#include "mohawk/riven_cursors.h" #include "common/macresman.h" #include "common/system.h" #include "common/winexe_ne.h" +#include "common/winexe_pe.h" #include "graphics/cursorman.h" #include "graphics/wincursor.h" @@ -84,15 +84,16 @@ void CursorManager::setCursor(uint16 id) { setDefaultCursor(); } -void CursorManager::decodeMacXorCursor(Common::SeekableReadStream *stream, byte *cursor) { +void CursorManager::setMacXorCursor(Common::SeekableReadStream *stream) { assert(stream); - assert(cursor); + + byte cursorBitmap[16 * 16]; // Get black and white data for (int i = 0; i < 32; i++) { byte imageByte = stream->readByte(); for (int b = 0; b < 8; b++) - cursor[i * 8 + b] = (imageByte & (0x80 >> b)) ? 1 : 2; + cursorBitmap[i * 8 + b] = (imageByte & (0x80 >> b)) ? 1 : 2; } // Apply mask data @@ -100,28 +101,18 @@ void CursorManager::decodeMacXorCursor(Common::SeekableReadStream *stream, byte byte imageByte = stream->readByte(); for (int b = 0; b < 8; b++) if ((imageByte & (0x80 >> b)) == 0) - cursor[i * 8 + b] = 0; + cursorBitmap[i * 8 + b] = 0; } -} -void CursorManager::setStandardCursor(Common::SeekableReadStream *stream) { - // The Broderbund devs decided to rip off the Mac format, it seems. - // However, they reversed the x/y hotspot. That makes it totally different!!!! - assert(stream); - - byte cursorBitmap[16 * 16]; - decodeMacXorCursor(stream, cursorBitmap); uint16 hotspotY = stream->readUint16BE(); uint16 hotspotX = stream->readUint16BE(); CursorMan.replaceCursor(cursorBitmap, 16, 16, hotspotX, hotspotY, 0); CursorMan.replaceCursorPalette(s_bwPalette, 1, 2); - - delete stream; } void DefaultCursorManager::setCursor(uint16 id) { - setStandardCursor(_vm->getResource(_tag, id)); + setMacXorCursor(_vm->getResource(_tag, id)); } MystCursorManager::MystCursorManager(MohawkEngine_Myst *vm) : _vm(vm) { @@ -168,119 +159,6 @@ void MystCursorManager::setDefaultCursor() { setCursor(kDefaultMystCursor); } -void RivenCursorManager::setCursor(uint16 id) { - // All of Riven's cursors are hardcoded. See riven_cursors.h for these definitions. - - switch (id) { - case 1002: - // Zip Mode - CursorMan.replaceCursor(s_zipModeCursor, 16, 16, 8, 8, 0); - CursorMan.replaceCursorPalette(s_zipModeCursorPalette, 1, ARRAYSIZE(s_zipModeCursorPalette) / 3); - break; - case 2003: - // Hand Over Object - CursorMan.replaceCursor(s_objectHandCursor, 16, 16, 8, 8, 0); - CursorMan.replaceCursorPalette(s_handCursorPalette, 1, ARRAYSIZE(s_handCursorPalette) / 3); - break; - case 2004: - // Grabbing/Using Object - CursorMan.replaceCursor(s_grabbingHandCursor, 13, 13, 6, 6, 0); - CursorMan.replaceCursorPalette(s_handCursorPalette, 1, ARRAYSIZE(s_handCursorPalette) / 3); - break; - case 3000: - // Standard Hand - CursorMan.replaceCursor(s_standardHandCursor, 15, 16, 6, 0, 0); - CursorMan.replaceCursorPalette(s_handCursorPalette, 1, ARRAYSIZE(s_handCursorPalette) / 3); - break; - case 3001: - // Pointing Left - CursorMan.replaceCursor(s_pointingLeftCursor, 15, 13, 0, 3, 0); - CursorMan.replaceCursorPalette(s_handCursorPalette, 1, ARRAYSIZE(s_handCursorPalette) / 3); - break; - case 3002: - // Pointing Right - CursorMan.replaceCursor(s_pointingRightCursor, 15, 13, 14, 3, 0); - CursorMan.replaceCursorPalette(s_handCursorPalette, 1, ARRAYSIZE(s_handCursorPalette) / 3); - break; - case 3003: - // Pointing Down (Palm Up) - CursorMan.replaceCursor(s_pointingDownCursorPalmUp, 13, 16, 3, 15, 0); - CursorMan.replaceCursorPalette(s_handCursorPalette, 1, ARRAYSIZE(s_handCursorPalette) / 3); - break; - case 3004: - // Pointing Up (Palm Up) - CursorMan.replaceCursor(s_pointingUpCursorPalmUp, 13, 16, 3, 0, 0); - CursorMan.replaceCursorPalette(s_handCursorPalette, 1, ARRAYSIZE(s_handCursorPalette) / 3); - break; - case 3005: - // Pointing Left (Curved) - CursorMan.replaceCursor(s_pointingLeftCursorBent, 15, 13, 0, 5, 0); - CursorMan.replaceCursorPalette(s_handCursorPalette, 1, ARRAYSIZE(s_handCursorPalette) / 3); - break; - case 3006: - // Pointing Right (Curved) - CursorMan.replaceCursor(s_pointingRightCursorBent, 15, 13, 14, 5, 0); - CursorMan.replaceCursorPalette(s_handCursorPalette, 1, ARRAYSIZE(s_handCursorPalette) / 3); - break; - case 3007: - // Pointing Down (Palm Down) - CursorMan.replaceCursor(s_pointingDownCursorPalmDown, 15, 16, 7, 15, 0); - CursorMan.replaceCursorPalette(s_handCursorPalette, 1, ARRAYSIZE(s_handCursorPalette) / 3); - break; - case 4001: - // Red Marble - CursorMan.replaceCursor(s_redMarbleCursor, 12, 12, 5, 5, 0); - CursorMan.replaceCursorPalette(s_redMarbleCursorPalette, 1, ARRAYSIZE(s_redMarbleCursorPalette) / 3); - break; - case 4002: - // Orange Marble - CursorMan.replaceCursor(s_orangeMarbleCursor, 12, 12, 5, 5, 0); - CursorMan.replaceCursorPalette(s_orangeMarbleCursorPalette, 1, ARRAYSIZE(s_orangeMarbleCursorPalette) / 3); - break; - case 4003: - // Yellow Marble - CursorMan.replaceCursor(s_yellowMarbleCursor, 12, 12, 5, 5, 0); - CursorMan.replaceCursorPalette(s_yellowMarbleCursorPalette, 1, ARRAYSIZE(s_yellowMarbleCursorPalette) / 3); - break; - case 4004: - // Green Marble - CursorMan.replaceCursor(s_greenMarbleCursor, 12, 12, 5, 5, 0); - CursorMan.replaceCursorPalette(s_greenMarbleCursorPalette, 1, ARRAYSIZE(s_greenMarbleCursorPalette) / 3); - break; - case 4005: - // Blue Marble - CursorMan.replaceCursor(s_blueMarbleCursor, 12, 12, 5, 5, 0); - CursorMan.replaceCursorPalette(s_blueMarbleCursorPalette, 1, ARRAYSIZE(s_blueMarbleCursorPalette) / 3); - break; - case 4006: - // Violet Marble - CursorMan.replaceCursor(s_violetMarbleCursor, 12, 12, 5, 5, 0); - CursorMan.replaceCursorPalette(s_violetMarbleCursorPalette, 1, ARRAYSIZE(s_violetMarbleCursorPalette) / 3); - break; - case 5000: - // Pellet - CursorMan.replaceCursor(s_pelletCursor, 8, 8, 4, 4, 0); - CursorMan.replaceCursorPalette(s_pelletCursorPalette, 1, ARRAYSIZE(s_pelletCursorPalette) / 3); - break; - case 9000: - // Hide Cursor - CursorMan.showMouse(false); - break; - default: - error("Cursor %d does not exist!", id); - } - - if (id != 9000) // Show Cursor - CursorMan.showMouse(true); - - // Should help in cases where we need to hide the cursor immediately. - g_system->updateScreen(); -} - -void RivenCursorManager::setDefaultCursor() { - setCursor(kRivenMainCursor); -} - NECursorManager::NECursorManager(const Common::String &appName) { _exe = new Common::NEResources(); @@ -333,22 +211,33 @@ void MacCursorManager::setCursor(uint16 id) { return; } - Common::SeekableReadStream *stream = _resFork->getResource(MKID_BE('CURS'), id); + // Try a color cursor first + Common::SeekableReadStream *stream = _resFork->getResource(MKID_BE('crsr'), id); - if (!stream) { - setDefaultCursor(); + if (stream) { + byte *cursor, *palette; + int width, height, hotspotX, hotspotY, keyColor, palSize; + + _resFork->convertCrsrCursor(stream, &cursor, width, height, hotspotX, hotspotY, keyColor, true, &palette, palSize); + + CursorMan.replaceCursor(cursor, width, height, hotspotX, hotspotY, keyColor); + CursorMan.replaceCursorPalette(palette, 0, palSize); + + delete[] cursor; + delete[] palette; + delete stream; return; } - byte cursorBitmap[16 * 16]; - decodeMacXorCursor(stream, cursorBitmap); - uint16 hotspotX = stream->readUint16BE(); - uint16 hotspotY = stream->readUint16BE(); + // Fall back to b&w cursors + stream = _resFork->getResource(MKID_BE('CURS'), id); - CursorMan.replaceCursor(cursorBitmap, 16, 16, hotspotX, hotspotY, 0); - CursorMan.replaceCursorPalette(s_bwPalette, 1, 2); - - delete stream; + if (stream) { + setMacXorCursor(stream); + delete stream; + } else { + setDefaultCursor(); + } } LivingBooksCursorManager_v2::LivingBooksCursorManager_v2() { @@ -367,10 +256,40 @@ LivingBooksCursorManager_v2::~LivingBooksCursorManager_v2() { void LivingBooksCursorManager_v2::setCursor(uint16 id) { if (_sysArchive && _sysArchive->hasResource(ID_TCUR, id)) { - setStandardCursor(_sysArchive->getResource(ID_TCUR, id)); + setMacXorCursor(_sysArchive->getResource(ID_TCUR, id)); } else { // TODO: Handle generated cursors } } +PECursorManager::PECursorManager(const Common::String &appName) { + _exe = new Common::PEResources(); + + if (!_exe->loadFromEXE(appName)) { + // Not all have cursors anyway, so this is not a problem + delete _exe; + _exe = 0; + } +} + +PECursorManager::~PECursorManager() { + delete _exe; +} + +void PECursorManager::setCursor(uint16 id) { + if (_exe) { + Graphics::WinCursorGroup *cursorGroup = Graphics::WinCursorGroup::createCursorGroup(*_exe, id); + + if (cursorGroup) { + Graphics::WinCursor *cursor = cursorGroup->cursors[0].cursor; + CursorMan.replaceCursor(cursor->getSurface(), cursor->getWidth(), cursor->getHeight(), cursor->getHotspotX(), cursor->getHotspotY(), cursor->getKeyColor()); + CursorMan.replaceCursorPalette(cursor->getPalette(), 0, 256); + return; + } + } + + // Last resort (not all have cursors) + setDefaultCursor(); +} + } // End of namespace Mohawk diff --git a/engines/mohawk/cursors.h b/engines/mohawk/cursors.h index a542ddb7c3..ae48b558b7 100644 --- a/engines/mohawk/cursors.h +++ b/engines/mohawk/cursors.h @@ -31,6 +31,7 @@ namespace Common { class MacResManager; class NEResources; + class PEResources; class SeekableReadStream; class String; } @@ -82,11 +83,8 @@ public: virtual void setDefaultCursor(); protected: - // Handles the Mac version of the xor/and map cursor - void decodeMacXorCursor(Common::SeekableReadStream *stream, byte *cursor); - - // Set a tCUR resource as the current cursor - void setStandardCursor(Common::SeekableReadStream *stream); + // Set a Mac XOR/AND map cursor to the screen + void setMacXorCursor(Common::SeekableReadStream *stream); }; // The default Mohawk cursor manager @@ -120,19 +118,7 @@ private: MystBitmap *_bmpDecoder; }; - -// The cursor manager for Riven -// Uses hardcoded cursors -class RivenCursorManager : public CursorManager { -public: - RivenCursorManager() {} - ~RivenCursorManager() {} - - void setCursor(uint16 id); - void setDefaultCursor(); -}; - -// The cursor manager for NE exe's +// The cursor manager for NE EXE's class NECursorManager : public CursorManager { public: NECursorManager(const Common::String &appName); @@ -169,6 +155,18 @@ private: MohawkArchive *_sysArchive; }; +// The cursor manager for PE EXE's +class PECursorManager : public CursorManager { +public: + PECursorManager(const Common::String &appName); + ~PECursorManager(); + + void setCursor(uint16 id); + +private: + Common::PEResources *_exe; +}; + } // End of namespace Mohawk #endif diff --git a/engines/mohawk/riven.cpp b/engines/mohawk/riven.cpp index abc7f5304e..19adf3fe2f 100644 --- a/engines/mohawk/riven.cpp +++ b/engines/mohawk/riven.cpp @@ -120,7 +120,15 @@ Common::Error MohawkEngine_Riven::run() { _externalScriptHandler = new RivenExternal(this); _optionsDialog = new RivenOptionsDialog(this); _scriptMan = new RivenScriptManager(this); - _cursor = new RivenCursorManager(); + + // Create the cursor manager + // TODO: Error handling when none can be found + if (Common::File::exists("rivendmo.exe")) + _cursor = new PECursorManager("rivendmo.exe"); + else if (Common::File::exists("riven.exe")) + _cursor = new PECursorManager("riven.exe"); + else // last resort: try the Mac executable + _cursor = new MacCursorManager("Riven"); _rnd = new Common::RandomSource(); g_eventRec.registerRandomSource(*_rnd, "riven"); @@ -135,6 +143,7 @@ Common::Error MohawkEngine_Riven::run() { // Start at main cursor _cursor->setCursor(kRivenMainCursor); + _system->updateScreen(); // Let's begin, shall we? if (getFeatures() & GF_DEMO) { @@ -488,10 +497,12 @@ void MohawkEngine_Riven::checkHotspotChange() { if (_curHotspot != hotspotIndex) { _curHotspot = hotspotIndex; _cursor->setCursor(_hotspots[_curHotspot].mouse_cursor); + _system->updateScreen(); } } else { _curHotspot = -1; _cursor->setCursor(kRivenMainCursor); + _system->updateScreen(); } } diff --git a/engines/mohawk/riven_cursors.h b/engines/mohawk/riven_cursors.h deleted file mode 100644 index dadfdf0549..0000000000 --- a/engines/mohawk/riven_cursors.h +++ /dev/null @@ -1,670 +0,0 @@ -/* ScummVM - Graphic Adventure Engine - * - * ScummVM is the legal property of its developers, whose names - * are too numerous to list here. Please refer to the COPYRIGHT - * file distributed with this source distribution. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - * $URL$ - * $Id$ - * - */ - -namespace Mohawk { - -////////////////////////////////////////////// -// Cursors and Cursor Palettes -////////////////////////////////////////////// - -//////////////////////////////////////// -// Zip Mode Cursor (16x16): -// Shown when a zip mode spot is active -// -// 0 = Transparent -// 1 = Black (0x000000) -// 2 = Yellow (0xDCFF00) -//////////////////////////////////////// -static const byte s_zipModeCursor[] = { - 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 1, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 1, 1, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 1, 1, 0, 0, 1, 2, 1, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 1, 2, 1, 0, 1, 2, 1, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 1, 2, 1, 1, 2, 2, 1, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 1, 2, 2, 1, 2, 2, 2, 1, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 1, 2, 2, 2, 2, 2, 1, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 1, 2, 2, 2, 2, 2, 1, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 1, 2, 2, 2, 1, 2, 2, 1, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 1, 2, 2, 1, 1, 2, 1, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 1, 2, 1, 0, 1, 2, 1, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 1, 2, 1, 0, 0, 1, 1, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 1, 1, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 1, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 -}; - - -//////////////////////////////////////// -// Zip Mode Cursor Palette: -// Palette For The Zip Mode Cursor -//////////////////////////////////////// -static const byte s_zipModeCursorPalette[] = { - 0x00, 0x00, 0x00, // Black - 0xDC, 0xFF, 0x00 // Yellow -}; - - -//////////////////////////////////////// -// Hand Over Object Cursor (16x16): -// Shown when over a hotspot that's interactive -// -// 0 = Transparent -// 1 = Black (0x000000) -// 2 = Light Peach (0xEDCD96) -// 3 = Brown (0x8A672F) -// 4 = Dark Peach (0xE89A62) -//////////////////////////////////////// -static const byte s_objectHandCursor[] = { - 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 1, 1, 0, 1, 2, 3, 1, 1, 1, 0, 0, 0, 0, - 0, 0, 1, 2, 3, 1, 1, 2, 3, 1, 2, 3, 1, 0, 0, 0, - 0, 0, 1, 2, 3, 1, 1, 4, 3, 1, 2, 3, 1, 0, 1, 0, - 0, 0, 0, 1, 2, 3, 1, 2, 3, 1, 4, 3, 1, 1, 2, 1, - 0, 0, 0, 1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 1, - 0, 1, 1, 0, 1, 2, 2, 2, 2, 2, 2, 3, 1, 2, 3, 1, - 1, 2, 2, 1, 1, 2, 2, 2, 4, 2, 4, 2, 2, 4, 2, 1, - 1, 3, 4, 2, 1, 2, 4, 2, 2, 2, 2, 2, 4, 4, 1, 0, - 0, 1, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 4, 3, 1, 0, - 0, 0, 1, 3, 2, 2, 2, 2, 2, 2, 2, 4, 4, 3, 1, 0, - 0, 0, 1, 3, 2, 2, 2, 2, 2, 2, 2, 4, 3, 1, 0, 0, - 0, 0, 0, 1, 2, 2, 2, 2, 2, 2, 2, 3, 3, 1, 0, 0, - 0, 0, 0, 0, 1, 2, 2, 2, 2, 2, 4, 3, 1, 0, 0, 0, - 0, 0, 0, 0, 0, 1, 2, 2, 2, 2, 4, 3, 1, 0, 0, 0, - 0, 0, 0, 0, 0, 1, 2, 2, 2, 2, 4, 3, 1, 0, 0, 0 -}; - - -//////////////////////////////////////// -// Grabbing Hand Cursor (13x13): -// Shown when interacting with an object -// -// 0 = Transparent -// 1 = Black (0x000000) -// 2 = Light Peach (0xEDCD96) -// 3 = Brown (0x8A672F) -// 4 = Dark Peach (0xE89A62) -//////////////////////////////////////// -static const byte s_grabbingHandCursor[] = { - 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, - 0, 0, 1, 1, 1, 2, 3, 1, 1, 1, 0, 0, 0, - 0, 1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 1, 0, - 0, 1, 2, 2, 2, 2, 2, 2, 2, 3, 1, 2, 1, - 0, 1, 1, 2, 2, 2, 4, 2, 4, 2, 2, 4, 1, - 1, 2, 1, 2, 4, 2, 2, 2, 2, 2, 4, 4, 1, - 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 4, 3, 1, - 1, 3, 2, 2, 2, 2, 2, 2, 2, 4, 4, 3, 1, - 1, 3, 2, 2, 2, 2, 2, 2, 2, 4, 3, 1, 0, - 0, 1, 2, 2, 2, 2, 2, 2, 2, 3, 3, 1, 0, - 0, 0, 1, 2, 2, 2, 2, 2, 4, 3, 1, 0, 0, - 0, 0, 0, 1, 2, 2, 2, 2, 4, 3, 1, 0, 0, - 0, 0, 0, 1, 2, 2, 2, 2, 4, 3, 1, 0, 0 -}; - - -//////////////////////////////////////// -// Standard Hand Cursor (15x16): -// Standard Cursor -// -// 0 = Transparent -// 1 = Black (0x000000) -// 2 = Light Peach (0xEDCD96) -// 3 = Brown (0x8A672F) -// 4 = Dark Peach (0xE89A62) -//////////////////////////////////////// -static const byte s_standardHandCursor[] = { - 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 1, 4, 4, 1, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 1, 2, 3, 1, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 1, 2, 4, 1, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 1, 2, 4, 1, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 1, 2, 4, 1, 0, 0, 0, 0, 0, 0, - 0, 1, 1, 0, 0, 1, 2, 4, 1, 1, 1, 1, 1, 0, 0, - 1, 4, 2, 1, 0, 1, 2, 4, 1, 4, 1, 4, 1, 1, 1, - 0, 1, 3, 2, 1, 1, 2, 4, 1, 4, 1, 4, 1, 4, 1, - 0, 0, 1, 4, 2, 1, 2, 2, 4, 2, 4, 2, 1, 4, 1, - 0, 0, 1, 4, 2, 1, 2, 2, 2, 2, 2, 2, 2, 3, 1, - 0, 0, 0, 1, 4, 2, 2, 2, 2, 2, 2, 2, 4, 3, 1, - 0, 0, 0, 0, 1, 2, 2, 2, 2, 2, 2, 2, 4, 3, 1, - 0, 0, 0, 0, 1, 2, 2, 2, 2, 2, 2, 2, 3, 1, 0, - 0, 0, 0, 0, 0, 1, 2, 2, 2, 2, 2, 4, 3, 1, 0, - 0, 0, 0, 0, 0, 1, 2, 2, 2, 2, 2, 4, 3, 1, 0 -}; - - -//////////////////////////////////////// -// Pointing Left Cursor (15x13): -// Cursor When Over A Hotspot That Allows You To Move Left -// -// 0 = Transparent -// 1 = Black (0x000000) -// 2 = Light Peach (0xEDCD96) -// 3 = Brown (0x8A672F) -// 4 = Dark Peach (0xE89A62) -//////////////////////////////////////// -static const byte s_pointingLeftCursor[] = { - 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 1, 3, 2, 2, 2, 1, 1, 0, 0, - 0, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 4, 3, 1, 1, - 1, 4, 2, 2, 2, 2, 1, 2, 3, 2, 2, 2, 4, 4, 4, - 1, 4, 4, 4, 4, 4, 1, 2, 1, 3, 4, 2, 2, 2, 2, - 0, 1, 1, 1, 1, 1, 1, 2, 1, 3, 3, 4, 2, 2, 2, - 0, 0, 0, 0, 0, 1, 1, 1, 1, 3, 3, 3, 4, 4, 2, - 0, 0, 0, 0, 0, 1, 2, 2, 2, 4, 1, 3, 4, 2, 2, - 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 3, 4, 2, 2, - 0, 0, 0, 0, 0, 1, 2, 2, 2, 2, 2, 1, 4, 2, 4, - 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 4, 4, 1, - 0, 0, 0, 0, 0, 0, 1, 2, 2, 2, 2, 1, 1, 1, 0, - 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0 -}; - - -//////////////////////////////////////// -// Pointing Right Cursor (15x13): -// Cursor When Over A Hotspot That Allows You To Move Right -// -// 0 = Transparent -// 1 = Black (0x000000) -// 2 = Light Peach (0xEDCD96) -// 3 = Brown (0x8A672F) -// 4 = Dark Peach (0xE89A62) -//////////////////////////////////////// -static const byte s_pointingRightCursor[] = { - 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 1, 1, 2, 2, 2, 3, 1, 0, 0, 0, 0, 0, 0, - 1, 1, 3, 4, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 0, - 4, 4, 4, 2, 2, 2, 3, 2, 1, 4, 4, 4, 4, 4, 1, - 2, 2, 2, 2, 4, 3, 1, 2, 1, 2, 2, 2, 2, 4, 1, - 2, 2, 2, 4, 3, 3, 1, 2, 1, 1, 1, 1, 1, 1, 0, - 2, 4, 4, 3, 3, 3, 1, 1, 1, 1, 0, 0, 0, 0, 0, - 2, 2, 4, 3, 1, 4, 2, 2, 2, 1, 0, 0, 0, 0, 0, - 2, 2, 4, 3, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, - 4, 2, 4, 1, 2, 2, 2, 2, 2, 1, 0, 0, 0, 0, 0, - 1, 4, 4, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, - 0, 1, 1, 1, 2, 2, 2, 2, 1, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0 -}; - - -//////////////////////////////////////// -// Pointing Down Cursor (Palm Up)(13x16): -// Cursor When Over A Hotspot That Allows You To Move Down -// -// 0 = Transparent -// 1 = Black (0x000000) -// 2 = Light Peach (0xEDCD96) -// 3 = Brown (0x8A672F) -// 4 = Dark Peach (0xE89A62) -//////////////////////////////////////// -static const byte s_pointingDownCursorPalmUp[] = { - 0, 0, 1, 4, 2, 2, 2, 2, 2, 4, 1, 0, 0, - 0, 0, 1, 4, 2, 2, 4, 2, 2, 2, 4, 1, 0, - 0, 1, 3, 4, 2, 2, 4, 4, 4, 4, 4, 1, 0, - 0, 1, 4, 2, 2, 4, 3, 3, 3, 1, 1, 1, 1, - 1, 2, 2, 2, 4, 3, 3, 1, 1, 2, 1, 2, 1, - 1, 2, 2, 2, 3, 3, 3, 4, 1, 2, 1, 2, 1, - 1, 2, 2, 3, 1, 1, 1, 2, 1, 2, 1, 2, 1, - 1, 3, 2, 2, 2, 2, 1, 2, 1, 2, 1, 2, 1, - 0, 1, 1, 1, 1, 1, 1, 2, 1, 2, 1, 1, 1, - 0, 0, 1, 2, 4, 1, 1, 1, 1, 1, 1, 0, 0, - 0, 0, 1, 2, 4, 1, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 1, 2, 4, 1, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 1, 2, 4, 1, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 1, 2, 4, 1, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 1, 4, 4, 1, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0 -}; - - -//////////////////////////////////////// -// Pointing Up Cursor (Palm Up)(13x16): -// Cursor When Over A Hotspot That Allows You To Move Up -// -// 0 = Transparent -// 1 = Black (0x000000) -// 2 = Light Peach (0xEDCD96) -// 3 = Brown (0x8A672F) -// 4 = Dark Peach (0xE89A62) -//////////////////////////////////////// -static const byte s_pointingUpCursorPalmUp[] = { - 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 1, 4, 4, 1, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 1, 2, 4, 1, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 1, 2, 4, 1, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 1, 2, 4, 1, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 1, 2, 4, 1, 0, 0, - 0, 0, 1, 1, 1, 1, 1, 1, 2, 4, 1, 0, 0, - 1, 1, 1, 2, 1, 2, 1, 1, 1, 1, 1, 1, 0, - 1, 2, 1, 2, 1, 2, 1, 2, 2, 2, 2, 3, 1, - 1, 2, 1, 2, 1, 2, 1, 1, 1, 3, 2, 2, 1, - 1, 2, 1, 2, 1, 4, 3, 3, 3, 2, 2, 2, 1, - 1, 2, 1, 2, 1, 1, 3, 3, 4, 2, 2, 2, 1, - 1, 1, 1, 1, 3, 3, 3, 4, 2, 2, 4, 1, 0, - 0, 1, 4, 4, 4, 4, 4, 2, 2, 4, 3, 1, 0, - 0, 1, 4, 2, 2, 2, 4, 2, 2, 4, 1, 0, 0, - 0, 0, 1, 4, 2, 2, 2, 2, 2, 4, 1, 0, 0 -}; - - -//////////////////////////////////////// -// Pointing Left Cursor (Bent)(15x13): -// Cursor When Over A Hotspot That Allows You To Turn Left 180 Degrees -// -// 0 = Transparent -// 1 = Black (0x000000) -// 2 = Light Peach (0xEDCD96) -// 3 = Brown (0x8A672F) -// 4 = Dark Peach (0xE89A62) -//////////////////////////////////////// -static const byte s_pointingLeftCursorBent[] = { - 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 1, 3, 2, 2, 2, 1, 1, 0, 0, - 0, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 4, 3, 1, 1, - 1, 3, 2, 4, 4, 2, 1, 2, 3, 3, 2, 2, 4, 4, 4, - 1, 2, 4, 3, 3, 4, 1, 2, 1, 3, 4, 2, 2, 2, 2, - 1, 4, 4, 1, 1, 1, 1, 2, 1, 1, 3, 4, 2, 2, 2, - 1, 1, 1, 0, 0, 1, 1, 1, 1, 3, 3, 3, 4, 4, 2, - 0, 0, 0, 0, 0, 1, 2, 2, 2, 4, 1, 3, 4, 3, 2, - 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 3, 4, 2, 2, - 0, 0, 0, 0, 0, 1, 2, 2, 2, 2, 2, 1, 4, 2, 4, - 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 4, 4, 1, - 0, 0, 0, 0, 0, 0, 1, 2, 2, 2, 2, 1, 1, 1, 0, - 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0 -}; - - -//////////////////////////////////////// -// Pointing Right Cursor (Bent)(15x13): -// Cursor When Over A Hotspot That Allows You To Turn Right 180 Degrees -// -// 0 = Transparent -// 1 = Black (0x000000) -// 2 = Light Peach (0xEDCD96) -// 3 = Brown (0x8A672F) -// 4 = Dark Peach (0xE89A62) -//////////////////////////////////////// -static const byte s_pointingRightCursorBent[] = { - 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 1, 1, 2, 2, 2, 3, 1, 0, 0, 0, 0, 0, 0, - 1, 1, 3, 4, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 0, - 4, 4, 4, 2, 2, 3, 3, 2, 1, 2, 4, 4, 2, 3, 1, - 2, 2, 2, 2, 4, 3, 1, 2, 1, 4, 3, 3, 4, 2, 1, - 2, 2, 2, 4, 3, 1, 1, 2, 1, 1, 1, 1, 4, 4, 1, - 2, 4, 4, 3, 3, 3, 1, 1, 1, 1, 0, 0, 1, 1, 1, - 2, 3, 4, 3, 1, 4, 2, 2, 2, 1, 0, 0, 0, 0, 0, - 2, 2, 4, 3, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, - 4, 2, 4, 1, 2, 2, 2, 2, 2, 1, 0, 0, 0, 0, 0, - 1, 4, 4, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, - 0, 1, 1, 1, 2, 2, 2, 2, 1, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0 -}; - - -//////////////////////////////////////// -// Pointing Down Cursor (Palm Down)(15x16): -// Similar to Standard Cursor -// -// 0 = Transparent -// 1 = Black (0x000000) -// 2 = Light Peach (0xEDCD96) -// 3 = Brown (0x8A672F) -// 4 = Dark Peach (0xE89A62) -//////////////////////////////////////// -static const byte s_pointingDownCursorPalmDown[] = { - 0, 1, 3, 4, 2, 2, 2, 2, 2, 1, 0, 0, 0, 0, 0, - 0, 1, 3, 4, 2, 2, 2, 2, 2, 1, 0, 0, 0, 0, 0, - 0, 1, 3, 2, 2, 2, 2, 2, 2, 2, 1, 0, 0, 0, 0, - 1, 3, 4, 2, 2, 2, 2, 2, 2, 2, 1, 0, 0, 0, 0, - 1, 3, 4, 2, 2, 2, 2, 2, 2, 2, 4, 1, 0, 0, 0, - 1, 3, 2, 3, 2, 2, 2, 2, 2, 1, 2, 4, 1, 0, 0, - 1, 4, 1, 2, 2, 3, 2, 3, 2, 1, 2, 4, 1, 0, 0, - 1, 4, 1, 4, 1, 4, 1, 4, 4, 1, 1, 2, 3, 1, 0, - 0, 1, 1, 4, 1, 4, 1, 4, 2, 1, 0, 1, 2, 4, 1, - 0, 0, 1, 1, 1, 1, 1, 4, 2, 1, 0, 0, 1, 1, 0, - 0, 0, 0, 0, 0, 0, 1, 4, 4, 1, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 1, 4, 2, 1, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 1, 4, 2, 1, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 1, 3, 2, 1, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 1, 4, 4, 1, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0 -}; - -//////////////////////////////////////// -// Hand Cursor Palette: -// Palette For All Hand Cursors -//////////////////////////////////////// -static const byte s_handCursorPalette[] = { - 0x00, 0x00, 0x00, // Black - 0xED, 0xCD, 0x96, // Light Peach - 0x8A, 0x67, 0x2F, // Brown - 0xE8, 0x9A, 0x62 // Dark Peach -}; - - -//////////////////////////////////////// -// Pellet Cursor (8x8): -// Cursor When Using The Pellet In The Frog Trap -// -// 0 = Transparent -// 1 = Light Olive Green (0x5D6730) -// 2 = Maroon (0x5E3333) -// 3 = Light Gray (0x555555) -// 4 = Medium Gray (0x444444) -// 5 = Dark Gray (0x333333) -// 6 = Dark Green (0x2D3300) -// 7 = Darkest Gray (0x222222) -//////////////////////////////////////// -static const byte s_pelletCursor[] = { - 0, 0, 1, 1, 2, 3, 0, 0, - 0, 2, 1, 4, 1, 2, 5, 0, - 4, 1, 4, 1, 2, 1, 5, 4, - 4, 2, 1, 2, 1, 1, 2, 6, - 6, 4, 2, 1, 4, 4, 1, 5, - 5, 6, 5, 2, 1, 2, 4, 4, - 0, 7, 5, 5, 4, 2, 5, 0, - 0, 0, 5, 6, 6, 5, 0, 0 -}; - -//////////////////////////////////////// -// Pellet Cursor Palette: -// Palette For The Pellet Cursor -//////////////////////////////////////// -static const byte s_pelletCursorPalette[] = { - 0x5D, 0x67, 0x30, - 0x5E, 0x33, 0x33, - 0x55, 0x55, 0x55, - 0x44, 0x44, 0x44, - 0x33, 0x33, 0x33, - 0x2D, 0x33, 0x00, - 0x22, 0x22, 0x22 -}; - -//////////////////////////////////////// -// Red Marble Cursor (12x12): -// Cursor When Holding The Red Marble -//////////////////////////////////////// -static const byte s_redMarbleCursor[] = { - 0, 0, 0, 0, 1, 2, 2, 2, 0, 0, 0, 0, - 0, 0, 3, 4, 2, 5, 2, 2, 2, 2, 0, 0, - 0, 6, 1, 1, 2, 2, 5, 2, 2, 2, 2, 0, - 0, 6, 3, 4, 5, 2, 2, 7, 8, 5, 2, 0, - 9, 6, 10,11,2, 2, 2, 12,13,2, 2, 2, - 14,10,6, 4, 1, 2, 8, 2, 2, 5, 2, 2, - 15,16,6, 3, 1, 2, 2, 2, 2, 2, 2, 5, - 17,9,18, 3, 4, 4, 4, 5, 2, 5, 1, 2, - 0, 16,9, 6, 6, 19,1, 20,1, 4, 11,0, - 0, 17,15,18,9, 10,6, 10,3, 21,4, 0, - 0, 0, 18,15,9, 18,6, 22,10,23,0, 0, - 0, 0, 0, 0, 15,15,16,9, 0, 0, 0, 0 -}; - - -//////////////////////////////////////// -// Red Marble Cursor Palette: -// Palette For The Red Marble Cursor -//////////////////////////////////////// -static const byte s_redMarbleCursorPalette[] = { - 0xb8, 0x33, 0x32, - 0xe5, 0x33, 0x31, - 0x98, 0x06, 0x00, - 0xb8, 0x00, 0x34, - 0xe6, 0x00, 0x34, - 0x7a, 0x04, 0x00, - 0xe8, 0x9a, 0x62, - 0xea, 0x31, 0x67, - 0x6a, 0x03, 0x00, - 0x8c, 0x00, 0x35, - 0xb6, 0x36, 0x00, - 0xed, 0xcd, 0x96, - 0xe9, 0x66, 0x65, - 0x5b, 0x35, 0x00, - 0x5b, 0x02, 0x00, - 0x5f, 0x00, 0x35, - 0x4c, 0x01, 0x00, - 0x5e, 0x33, 0x33, - 0x89, 0x05, 0x00, - 0xb6, 0x08, 0x00, - 0xa7, 0x07, 0x00, - 0x88, 0x36, 0x00, - 0x8b, 0x33, 0x33 -}; - -//////////////////////////////////////// -// Orange Marble Cursor (12x12): -// Cursor When Holding The Orange Marble -//////////////////////////////////////// -static const byte s_orangeMarbleCursor[] = { - 0, 0, 0, 0, 1, 2, 2, 3, 0, 0, 0, 0, - 0, 0, 4, 5, 2, 2, 3, 3, 3, 3, 0, 0, - 0, 6, 7, 4, 2, 1, 2, 2, 3, 3, 3, 0, - 0, 6, 6, 7, 1, 2, 3, 8, 9, 2, 10,0, - 11,12,7, 4, 2, 3, 3, 13,9, 2, 2, 1, - 14,15,6, 4, 2, 16,3, 3, 2, 1, 1, 1, - 14,14,12,17,4, 2, 2, 1, 2, 1, 2, 1, - 14,18,12,6, 4, 4, 4, 19,2, 19,20,4, - 0, 14,14,15,6, 15,6, 4, 4, 4, 4, 0, - 0, 14,11,14,14,12,12,12,17,6, 17,0, - 0, 0, 14,14,17,14,17,6, 6, 17,0, 0, - 0, 0, 0, 0, 14,11,14,11,0, 0, 0, 0 -}; - -//////////////////////////////////////// -// Orange Marble Cursor Palette: -// Palette For The Orange Marble Cursor -//////////////////////////////////////// -static const byte s_orangeMarbleCursorPalette[] = { - 0xe1, 0x9e, 0x00, - 0xe3, 0x9b, 0x28, - 0xe2, 0xcf, 0x20, - 0xb5, 0x6a, 0x00, - 0xb6, 0x9b, 0x29, - 0x87, 0x69, 0x00, - 0xb7, 0x67, 0x2f, - 0xe9, 0xff, 0x93, - 0xe1, 0xff, 0x5a, - 0xe0, 0xd0, 0x00, - 0x5e, 0x33, 0x33, - 0x88, 0x36, 0x00, - 0xf3, 0xff, 0xc9, - 0x5b, 0x35, 0x00, - 0x8b, 0x33, 0x33, - 0xe6, 0xce, 0x5f, - 0x8a, 0x67, 0x2f, - 0x5d, 0x67, 0x30, - 0xe2, 0x6a, 0x00, - 0xb3, 0x9d, 0x00 -}; - -//////////////////////////////////////// -// Yellow Marble Cursor (12x12): -// Cursor When Holding The Yellow Marble -//////////////////////////////////////// -static const byte s_yellowMarbleCursor[] = { - 0, 0, 0, 0, 1, 1, 1, 2, 0, 0, 0, 0, - 0, 0, 3, 4, 1, 1, 1, 5, 6, 6, 0, 0, - 0, 3, 3, 7, 1, 1, 1, 1, 2, 1, 6, 0, - 0, 3, 3, 3, 3, 1, 1, 8, 6, 1, 6, 0, - 9, 9, 3, 3, 1, 1, 2, 10,8, 1, 1, 2, - 11,9, 3, 3, 1, 1, 1, 1, 1, 1, 5, 1, - 9, 9, 12,3, 3, 1, 1, 1, 1, 1, 1, 1, - 9, 9, 9, 3, 3, 3, 3, 3, 1, 1, 1, 1, - 0, 11,9, 9, 12,3, 3, 3, 3, 3, 3, 0, - 0, 9, 9, 13,9, 14,12,3, 3, 3, 3, 0, - 0, 0, 9, 9, 9, 12,14,3, 13,3, 0, 0, - 0, 0, 0, 0, 11,9, 11,9, 0, 0, 0, 0 -}; - -//////////////////////////////////////// -// Yellow Marble Cursor Palette: -// Palette For The Yellow Marble Cursor -//////////////////////////////////////// -static const byte s_yellowMarbleCursorPalette[] = { - 0xb3, 0xd0, 0x00, - 0xb0, 0xff, 0x00, - 0x86, 0x9c, 0x00, - 0x87, 0xd0, 0x00, - 0xe0, 0xd0, 0x00, - 0xdc, 0xff, 0x00, - 0xb3, 0x9d, 0x00, - 0xdc, 0xff, 0x11, - 0x5a, 0x68, 0x00, - 0xe1, 0xff, 0x5a, - 0x5d, 0x67, 0x30, - 0x87, 0x69, 0x00, - 0x88, 0x9b, 0x2a, - 0x5a, 0x9c, 0x00 -}; - -//////////////////////////////////////// -// Green Marble Cursor (12x12): -// Cursor When Holding The Green Marble -//////////////////////////////////////// -static const byte s_greenMarbleCursor[] = { - 0, 0, 0, 0, 1, 2, 3, 3, 0, 0, 0, 0, - 0, 0, 4, 5, 2, 1, 2, 3, 6, 6, 0, 0, - 0, 7, 5, 8, 8, 1, 1, 2, 3, 6, 6, 0, - 0, 7, 7, 4, 8, 1, 2, 9, 6, 2, 6, 0, - 10,7, 7, 4, 1, 2, 3, 11,12,2, 2, 3, - 13,13,7, 4, 1, 2, 3, 2, 1, 2, 2, 3, - 14,13,7, 7, 5, 1, 1, 8, 2, 1, 1, 2, - 15,16,13,7, 4, 4, 5, 5, 1, 8, 1, 1, - 0, 15,13,7, 7, 7, 4, 4, 4, 5, 8, 0, - 0, 14,16,15,13, 7, 7, 7, 4,17,5, 0, - 0, 0, 10,16,13,13,13,17,18,17,0, 0, - 0, 0, 0, 0, 15,10,19,10,0, 0, 0, 0 -}; - -//////////////////////////////////////// -// Green Marble Cursor Palette: -// Palette For The Green Marble Cursor -//////////////////////////////////////// -static const byte s_greenMarbleCursorPalette[] = { - 0x0e, 0xd0, 0x00, - 0x0f, 0xe1, 0x00, - 0x10, 0xf2, 0x00, - 0x0b, 0x9c, 0x00, - 0x0c, 0xad, 0x00, - 0x11, 0xff, 0x00, - 0x09, 0x8a, 0x00, - 0x0d, 0xbe, 0x00, - 0x30, 0xff, 0x5a, - 0x0d, 0x67, 0x30, - 0x6b, 0xff, 0x92, - 0x00, 0xff, 0x28, - 0x08, 0x79, 0x00, - 0x05, 0x57, 0x00, - 0x30, 0x67, 0x30, - 0x06, 0x68, 0x00, - 0x00, 0x9b, 0x2c, - 0x2e, 0x9c, 0x00, - 0x2e, 0x68, 0x00 -}; - -//////////////////////////////////////// -// Blue Marble Cursor (12x12): -// Cursor When Holding The Blue Marble -//////////////////////////////////////// -static const byte s_blueMarbleCursor[] = { - 0, 0, 0, 0, 1, 2, 3, 3, 0, 0, 0, 0, - 0, 0, 4, 5, 2, 2, 6, 3, 7, 3, 0, 0, - 0, 8, 9, 5, 10,11,2, 6, 3, 3, 7, 0, - 0, 12,13,9, 10,11,6, 14,7, 6, 3, 0, - 15,8, 4, 13,2, 6, 3, 16,17,6, 6, 3, - 18,15,19,13,10,7, 3, 6, 2, 2, 6, 7, - 20,8, 18,4, 21,11,2, 10,6, 2, 2, 2, - 15,15,18,8, 13,9, 21,5, 11,10,2, 1, - 0, 8, 15,19,15,13,13,21,21,5, 9, 0, - 0, 22,20,15, 8,19,15,19,4, 9, 4, 0, - 0, 0, 15,20,15,15,19,15,9, 15,0, 0, - 0, 0, 0, 0, 20,15, 8,15,0, 0, 0, 0 -}; - -//////////////////////////////////////// -// Blue Marble Cursor Palette: -// Palette For The Blue Marble Cursor -//////////////////////////////////////// -static const byte s_blueMarbleCursorPalette[] = { - 0x6b, 0x00, 0xd2, - 0x66, 0x00, 0xe3, - 0x72, 0x00, 0xff, - 0x53, 0x2d, 0x9d, - 0x4e, 0x00, 0xaf, - 0x6d, 0x00, 0xf5, - 0x7d, 0x00, 0xff, - 0x44, 0x00, 0x69, - 0x56, 0x00, 0x9d, - 0x56, 0x00, 0xc0, - 0x5e, 0x00, 0xd2, - 0x2b, 0x31, 0x68, - 0x3f, 0x00, 0x8c, - 0x91, 0x22, 0xff, - 0x41, 0x31, 0x68, - 0xd7, 0x95, 0xff, - 0x77, 0x22, 0xff, - 0x2f, 0x00, 0x69, - 0x37, 0x00, 0x7a, - 0x27, 0x00, 0x58, - 0x46, 0x00, 0x9d, - 0x33, 0x33, 0x33 -}; - -//////////////////////////////////////// -// Violet Marble Cursor (12x12): -// Cursor When Holding The Violet Marble -//////////////////////////////////////// -static const byte s_violetMarbleCursor[] = { - 0, 0, 0, 0, 1, 1, 1, 2, 0, 0, 0, 0, - 0, 0, 3, 3, 1, 1, 1, 4, 2, 4, 0, 0, - 0, 3, 3, 3, 1, 5, 1, 1, 4, 2, 4, 0, - 0, 3, 3, 3, 3, 1, 1, 6, 4, 1, 2, 0, - 3, 7, 8, 3, 1, 1, 4, 9, 4, 1, 1, 4, - 8, 7, 8, 3, 10,4, 1, 1, 1, 1, 4, 1, - 8, 3, 8, 7, 3, 1, 1, 5, 1, 1, 1, 1, - 7, 7, 11,3, 3, 3, 3, 3, 1, 3, 1, 1, - 0, 8, 7, 7, 8, 8, 7, 3, 3, 3, 1, 0, - 0, 7, 8, 3, 11,7, 3, 11,3, 10,3, 0, - 0, 0, 8, 7, 3, 3, 7, 3, 3, 3, 0, 0, - 0, 0, 0, 0, 8, 7, 11,3, 0, 0, 0, 0 -}; - -//////////////////////////////////////// -// Violet Marble Cursor Palette: -// Palette For The Violet Marble Cursor -//////////////////////////////////////// -static const byte s_violetMarbleCursorPalette[] = { - 0xaa, 0x00, 0xd1, - 0xd8, 0x00, 0xff, - 0x76, 0x00, 0x9d, - 0xb5, 0x00, 0xff, - 0x87, 0x00, 0xd2, - 0xd7, 0x22, 0xff, - 0x68, 0x00, 0x69, - 0x44, 0x00, 0x69, - 0xd7, 0x5e, 0xff, - 0x9c, 0x00, 0x9d, - 0x56, 0x00, 0x9d -}; - -} // End of namespace Mohawk diff --git a/engines/mohawk/riven_external.cpp b/engines/mohawk/riven_external.cpp index 7da5515411..e6ea25c9a6 100644 --- a/engines/mohawk/riven_external.cpp +++ b/engines/mohawk/riven_external.cpp @@ -316,6 +316,7 @@ void RivenExternal::checkSliderCursorChange(uint16 startHotspot) { _vm->_cursor->setCursor(kRivenOpenHandCursor); else _vm->_cursor->setCursor(kRivenMainCursor); + _vm->_system->updateScreen(); break; } } @@ -341,6 +342,7 @@ void RivenExternal::dragDomeSlider(uint16 soundId, uint16 resetSlidersHotspot, u // We've clicked down, so show the closed hand cursor _vm->_cursor->setCursor(kRivenClosedHandCursor); + _vm->_system->updateScreen(); bool done = false; while (!done) { @@ -862,6 +864,7 @@ void RivenExternal::xbcheckcatch(uint16 argc, uint16 *argv) { void RivenExternal::xbait(uint16 argc, uint16 *argv) { // Set the cursor to the pellet _vm->_cursor->setCursor(kRivenPelletCursor); + _vm->_system->updateScreen(); // Loop until the player lets go (or quits) Common::Event event; @@ -881,6 +884,7 @@ void RivenExternal::xbait(uint16 argc, uint16 *argv) { // Set back the cursor _vm->_cursor->setCursor(kRivenMainCursor); + _vm->_system->updateScreen(); // Set the bait if we put it on the plate if (_vm->_hotspots[9].rect.contains(_vm->_system->getEventManager()->getMousePos())) { @@ -899,8 +903,8 @@ void RivenExternal::xbfreeytram(uint16 argc, uint16 *argv) { void RivenExternal::xbaitplate(uint16 argc, uint16 *argv) { // Remove the pellet from the plate and put it in your hand _vm->_gfx->drawPLST(3); - _vm->_gfx->updateScreen(); _vm->_cursor->setCursor(kRivenPelletCursor); + _vm->_gfx->updateScreen(); // Loop until the player lets go (or quits) Common::Event event; @@ -920,6 +924,7 @@ void RivenExternal::xbaitplate(uint16 argc, uint16 *argv) { // Set back the cursor _vm->_cursor->setCursor(kRivenMainCursor); + _vm->_system->updateScreen(); // Set the bait if we put it on the plate, remove otherwise if (_vm->_hotspots[9].rect.contains(_vm->_system->getEventManager()->getMousePos())) { @@ -988,23 +993,27 @@ void RivenExternal::xvalvecontrol(uint16 argc, uint16 *argv) { if (*valve == 0 && changeY <= -10) { *valve = 1; _vm->_cursor->setCursor(kRivenHideCursor); + _vm->_system->updateScreen(); _vm->_video->playMovieBlockingRiven(2); _vm->refreshCard(); } else if (*valve == 1) { if (changeX >= 0 && changeY >= 10) { *valve = 0; _vm->_cursor->setCursor(kRivenHideCursor); + _vm->_system->updateScreen(); _vm->_video->playMovieBlockingRiven(3); _vm->refreshCard(); } else if (changeX <= -10 && changeY <= 10) { *valve = 2; _vm->_cursor->setCursor(kRivenHideCursor); + _vm->_system->updateScreen(); _vm->_video->playMovieBlockingRiven(1); _vm->refreshCard(); } } else if (*valve == 2 && changeX >= 10) { *valve = 1; _vm->_cursor->setCursor(kRivenHideCursor); + _vm->_system->updateScreen(); _vm->_video->playMovieBlockingRiven(4); _vm->refreshCard(); } @@ -1219,6 +1228,7 @@ void RivenExternal::xgisland1490_domecheck(uint16 argc, uint16 *argv) { void RivenExternal::xgplateau3160_dopools(uint16 argc, uint16 *argv) { // Play the deactivation of a pool if one is active and a different one is activated _vm->_cursor->setCursor(kRivenHideCursor); + _vm->_system->updateScreen(); _vm->_video->playMovieBlockingRiven(*_vm->getVar("glkbtns") * 2); } @@ -1522,11 +1532,13 @@ void RivenExternal::xvga1300_carriage(uint16 argc, uint16 *argv) { // Run the gallows's carriage _vm->_cursor->setCursor(kRivenHideCursor); // Hide the cursor - _vm->_video->playMovieBlockingRiven(1); // Play handle movie + _vm->_system->updateScreen(); // Update + _vm->_video->playMovieBlockingRiven(1); // Play handle movie _vm->_gfx->scheduleTransition(15); // Set pan down transition _vm->changeToCard(_vm->matchRMAPToCard(0x18e77)); // Change to card facing up _vm->_cursor->setCursor(kRivenHideCursor); // Hide the cursor (again) - _vm->_video->playMovieBlockingRiven(4); // Play carriage beginning to drop + _vm->_system->updateScreen(); // Update + _vm->_video->playMovieBlockingRiven(4); // Play carriage beginning to drop _vm->_gfx->scheduleTransition(14); // Set pan up transition _vm->changeToCard(_vm->matchRMAPToCard(0x183a9)); // Change to card looking straight again _vm->_video->playMovieBlockingRiven(2); @@ -1560,19 +1572,22 @@ void RivenExternal::xvga1300_carriage(uint16 argc, uint16 *argv) { } _vm->_cursor->setCursor(kRivenHideCursor); // Hide the cursor + _vm->_system->updateScreen(); // Update if (gotClick) { _vm->_gfx->scheduleTransition(16); // Schedule dissolve transition _vm->changeToCard(_vm->matchRMAPToCard(0x18d4d)); // Move forward _vm->_cursor->setCursor(kRivenHideCursor); // Hide the cursor + _vm->_system->updateScreen(); // Update _vm->_system->delayMillis(500); // Delay a half second before changing again _vm->_gfx->scheduleTransition(12); // Schedule pan left transition _vm->changeToCard(_vm->matchRMAPToCard(0x18ab5)); // Turn right _vm->_cursor->setCursor(kRivenHideCursor); // Hide the cursor - _vm->_video->playMovieBlockingRiven(1); // Play carriage ride movie + _vm->_system->updateScreen(); // Update + _vm->_video->playMovieBlockingRiven(1); // Play carriage ride movie _vm->changeToCard(_vm->matchRMAPToCard(0x17167)); // We have arrived at the top } else - _vm->_video->playMovieBlockingRiven(3); // Too slow! + _vm->_video->playMovieBlockingRiven(3); // Too slow! } void RivenExternal::xjdome25_resetsliders(uint16 argc, uint16 *argv) { @@ -1603,6 +1618,7 @@ int RivenExternal::jspitElevatorLoop() { _vm->_cursor->setCursor(kRivenClosedHandCursor); _vm->_system->updateScreen(); + for (;;) { while (_vm->_system->getEventManager()->pollEvent(event)) { switch (event.type) { @@ -1766,6 +1782,7 @@ void RivenExternal::xschool280_playwhark(uint16 argc, uint16 *argv) { // Hide the cursor _vm->_cursor->setCursor(kRivenHideCursor); + _vm->_system->updateScreen(); // Play the spin movie _vm->_video->playMovieBlockingRiven(spinMLST); @@ -1831,6 +1848,7 @@ void RivenExternal::xorollcredittime(uint16 argc, uint16 *argv) { void RivenExternal::xbookclick(uint16 argc, uint16 *argv) { // Hide the cursor _vm->_cursor->setCursor(kRivenHideCursor); + _vm->_system->updateScreen(); // Let's hook onto our video VideoHandle video = _vm->_video->findVideoHandleRiven(argv[0]); @@ -1873,6 +1891,8 @@ void RivenExternal::xbookclick(uint16 argc, uint16 *argv) { _vm->_cursor->setCursor(kRivenOpenHandCursor); else _vm->_cursor->setCursor(kRivenMainCursor); + + _vm->_system->updateScreen(); // OK, Gehn has opened the trap book and has asked us to go in. Let's watch // and see what the player will do... @@ -1887,7 +1907,7 @@ void RivenExternal::xbookclick(uint16 argc, uint16 *argv) { _vm->_cursor->setCursor(kRivenOpenHandCursor); else _vm->_cursor->setCursor(kRivenMainCursor); - updateScreen = false; // Don't update twice, changing the cursor already updates the screen + updateScreen = true; break; case Common::EVENT_LBUTTONUP: if (hotspotRect.contains(_vm->_system->getEventManager()->getMousePos())) { @@ -1899,7 +1919,7 @@ void RivenExternal::xbookclick(uint16 argc, uint16 *argv) { _vm->_gfx->updateScreen(); // Update the screen _vm->_sound->playSound(0); // Play the link sound _vm->_video->activateMLST(7, _vm->getCurCard()); // Activate Gehn Link Video - _vm->_video->playMovieBlockingRiven(1); // Play Gehn Link Video + _vm->_video->playMovieBlockingRiven(1); // Play Gehn Link Video *_vm->getVar("agehn") = 4; // Set Gehn to the trapped state *_vm->getVar("atrapbook") = 1; // We've got the trap book again _vm->_sound->playSound(0); // Play the link sound again @@ -1924,6 +1944,7 @@ void RivenExternal::xbookclick(uint16 argc, uint16 *argv) { // Hide the cursor again _vm->_cursor->setCursor(kRivenHideCursor); + _vm->_system->updateScreen(); // If there was no click and this is the third time Gehn asks us to // use the trap book, he will shoot the player. Dead on arrival. @@ -2012,6 +2033,7 @@ uint16 RivenExternal::getComboDigit(uint32 correctCombo, uint32 digit) { void RivenExternal::xgwatch(uint16 argc, uint16 *argv) { // Hide the cursor _vm->_cursor->setCursor(kRivenHideCursor); + _vm->_system->updateScreen(); uint32 *prisonCombo = _vm->getVar("pcorrectorder"); uint32 soundTime = _vm->_system->getMillis() - 500; // Start the first sound instantly @@ -2173,6 +2195,7 @@ void RivenExternal::xtexterior300_telescopedown(uint16 argc, uint16 *argv) { // ...the telescope can't move down anymore. // Play the sound of not being able to move _vm->_cursor->setCursor(kRivenHideCursor); + _vm->_system->updateScreen(); _vm->_sound->playSoundBlocking(13); } } else { @@ -2206,6 +2229,7 @@ void RivenExternal::xtexterior300_telescopeup(uint16 argc, uint16 *argv) { if (*telescopePos == 5) { // Play the sound of not being able to move _vm->_cursor->setCursor(kRivenHideCursor); + _vm->_system->updateScreen(); _vm->_sound->playSoundBlocking(13); return; } diff --git a/engines/mohawk/riven_scripts.cpp b/engines/mohawk/riven_scripts.cpp index 5d459354e9..98452e1e09 100644 --- a/engines/mohawk/riven_scripts.cpp +++ b/engines/mohawk/riven_scripts.cpp @@ -424,6 +424,7 @@ void RivenScript::stopSound(uint16 op, uint16 argc, uint16 *argv) { void RivenScript::changeCursor(uint16 op, uint16 argc, uint16 *argv) { debug(2, "Change to cursor %d", argv[0]); _vm->_cursor->setCursor(argv[0]); + _vm->_system->updateScreen(); } // Command 14: pause script execution (delay in ms, u1) -- cgit v1.2.3 From 10dad00a799aeb5e05e0fec865d25b21e7745956 Mon Sep 17 00:00:00 2001 From: Matthew Hoops Date: Mon, 7 Mar 2011 10:56:55 -0500 Subject: MOHAWK: Improve error handling when data isn't found --- engines/mohawk/cursors.cpp | 2 ++ engines/mohawk/cursors.h | 7 +++++++ engines/mohawk/riven.cpp | 25 +++++++++++++++++++------ 3 files changed, 28 insertions(+), 6 deletions(-) (limited to 'engines') diff --git a/engines/mohawk/cursors.cpp b/engines/mohawk/cursors.cpp index fdf19b624a..4a9fcb2ff2 100644 --- a/engines/mohawk/cursors.cpp +++ b/engines/mohawk/cursors.cpp @@ -198,6 +198,8 @@ MacCursorManager::MacCursorManager(const Common::String &appName) { delete _resFork; _resFork = 0; } + } else { + _resFork = 0; } } diff --git a/engines/mohawk/cursors.h b/engines/mohawk/cursors.h index ae48b558b7..e6c417948f 100644 --- a/engines/mohawk/cursors.h +++ b/engines/mohawk/cursors.h @@ -81,6 +81,7 @@ public: virtual void hideCursor(); virtual void setCursor(uint16 id); virtual void setDefaultCursor(); + virtual bool hasSource() const { return false; } protected: // Set a Mac XOR/AND map cursor to the screen @@ -95,6 +96,7 @@ public: ~DefaultCursorManager() {} void setCursor(uint16 id); + bool hasSource() const { return true; } private: MohawkEngine *_vm; @@ -112,6 +114,7 @@ public: void hideCursor(); void setCursor(uint16 id); void setDefaultCursor(); + bool hasSource() const { return true; } private: MohawkEngine_Myst *_vm; @@ -125,6 +128,7 @@ public: ~NECursorManager(); void setCursor(uint16 id); + bool hasSource() const { return _exe != 0; } private: Common::NEResources *_exe; @@ -137,6 +141,7 @@ public: ~MacCursorManager(); void setCursor(uint16 id); + bool hasSource() const { return _resFork != 0; } private: Common::MacResManager *_resFork; @@ -150,6 +155,7 @@ public: ~LivingBooksCursorManager_v2(); void setCursor(uint16 id); + bool hasSource() const { return _sysArchive != 0; } private: MohawkArchive *_sysArchive; @@ -162,6 +168,7 @@ public: ~PECursorManager(); void setCursor(uint16 id); + bool hasSource() const { return _exe != 0; } private: Common::PEResources *_exe; diff --git a/engines/mohawk/riven.cpp b/engines/mohawk/riven.cpp index 19adf3fe2f..f4a3ad00c8 100644 --- a/engines/mohawk/riven.cpp +++ b/engines/mohawk/riven.cpp @@ -121,8 +121,10 @@ Common::Error MohawkEngine_Riven::run() { _optionsDialog = new RivenOptionsDialog(this); _scriptMan = new RivenScriptManager(this); + _rnd = new Common::RandomSource(); + g_eventRec.registerRandomSource(*_rnd, "riven"); + // Create the cursor manager - // TODO: Error handling when none can be found if (Common::File::exists("rivendmo.exe")) _cursor = new PECursorManager("rivendmo.exe"); else if (Common::File::exists("riven.exe")) @@ -130,16 +132,27 @@ Common::Error MohawkEngine_Riven::run() { else // last resort: try the Mac executable _cursor = new MacCursorManager("Riven"); - _rnd = new Common::RandomSource(); - g_eventRec.registerRandomSource(*_rnd, "riven"); - initVars(); + // We need to have a cursor source, or the game won't work + if (!_cursor->hasSource()) { + Common::String message = "You're missing a Riven executable. The Windows executable is 'riven.exe' or 'rivendemo.exe'. "; + message += "Using the 'arcriven.z' installer file also works. In addition, you can use the Mac 'Riven' executable."; + GUIErrorMessage(message); + warning("%s", message.c_str()); + return Common::kNoGameDataFoundError; + } + // Open extras.mhk for common images _extrasFile = new MohawkArchive(); - if (!_extrasFile->open("extras.mhk")) - error("Could not open extras.mhk"); + // We need extras.mhk for inventory images, marble images, and credits images + if (!_extrasFile->open("extras.mhk")) { + Common::String message = "You're missing a extras.mhk. Using the 'arcriven.z' installer file also works."; + GUIErrorMessage(message); + warning("%s", message.c_str()); + return Common::kNoGameDataFoundError; + } // Start at main cursor _cursor->setCursor(kRivenMainCursor); -- cgit v1.2.3 From 9c7166ccc95af78af6c4ba1169af8babfb7697d7 Mon Sep 17 00:00:00 2001 From: Matthew Hoops Date: Mon, 7 Mar 2011 11:02:50 -0500 Subject: MOHAWK: Error message consistency --- engines/mohawk/riven.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'engines') diff --git a/engines/mohawk/riven.cpp b/engines/mohawk/riven.cpp index f4a3ad00c8..d75c98bcd4 100644 --- a/engines/mohawk/riven.cpp +++ b/engines/mohawk/riven.cpp @@ -148,7 +148,7 @@ Common::Error MohawkEngine_Riven::run() { // We need extras.mhk for inventory images, marble images, and credits images if (!_extrasFile->open("extras.mhk")) { - Common::String message = "You're missing a extras.mhk. Using the 'arcriven.z' installer file also works."; + Common::String message = "You're missing 'extras.mhk'. Using the 'arcriven.z' installer file also works."; GUIErrorMessage(message); warning("%s", message.c_str()); return Common::kNoGameDataFoundError; -- cgit v1.2.3