/** * Returns the animation offsets of a image, dependent on the * images orientation flags. * @param hImg Iimage to get animation offset of * @param flags Images current flags * @param pAniX Gets set to new X animation offset * @param pAniY Gets set to new Y animation offset */ void GetAniOffset(SCNHANDLE hImg, int flags, int *pAniX, int *pAniY) { if (hImg) { const IMAGE *pImg = (const IMAGE *)LockMem(hImg); // set ani X *pAniX = (int16) FROM_LE_16(pImg->anioffX); // set ani Y *pAniY = (int16) FROM_LE_16(pImg->anioffY); if (flags & DMA_FLIPH) { // we are flipped horizontally // set ani X = -ani X + width - 1 *pAniX = -*pAniX + FROM_LE_16(pImg->imgWidth) - 1; } if (flags & DMA_FLIPV) { // we are flipped vertically // set ani Y = -ani Y + height - 1 *pAniY = -*pAniY + (FROM_LE_16(pImg->imgHeight) & ~C16_FLAG_MASK) - 1; } } else // null image *pAniX = *pAniY = 0; }
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; }
void Disk::openFile(uint8 fileNum) { // Validate that the file number is correct if (fileNum > 4) error("Invalid file number specified - %d", fileNum); // Only load up the new file if the current file number has changed if (fileNum == _fileNum) return; // Delete any existing open file handle if (_fileNum != 0xff) delete _fileHandle; _fileNum = fileNum; // Open up the the new file _fileHandle = new Common::File(); char sFilename[10]; if (_fileNum == 0) strcpy(sFilename, SUPPORT_FILENAME); else sprintf(sFilename, "disk%d.vga", _fileNum); _fileHandle->open(sFilename); if (!_fileHandle->isOpen()) error("Could not open %s", sFilename); // Validate the header char buffer[7]; uint32 bytesRead; bytesRead = _fileHandle->read(buffer, 6); buffer[6] = '\0'; if (strcmp(buffer, HEADER_IDENT_STRING) != 0) error("The file %s was not a valid VGA file", sFilename); uint16 fileFileNum = _fileHandle->readUint16BE(); if (fileFileNum != _fileNum) error("The file %s was not the correct file number", sFilename); // Read in the header entries uint32 headerSize = sizeof(FileEntry) * NUM_ENTRIES_IN_HEADER; if (_fileHandle->read(_entries, headerSize) != headerSize) error("The file %s had a corrupted header", sFilename); #ifdef SCUMM_BIG_ENDIAN // Process the read in header list to convert to big endian for (int i = 0; i < NUM_ENTRIES_IN_HEADER; ++i) { _entries[i].id = FROM_LE_16(_entries[i].id); _entries[i].size = FROM_LE_16(_entries[i].size); _entries[i].offset = FROM_LE_16(_entries[i].offset); } #endif }
/** * Give a object a new image and new orientation flags. * @param pAniObj Object to be updated * @param newflags Objects new flags * @param hNewImg Objects new image */ void AnimateObjectFlags(OBJECT *pAniObj, int newflags, SCNHANDLE hNewImg) { // validate object pointer assert(isValidObject(pAniObj)); if (pAniObj->hImg != hNewImg || (pAniObj->flags & DMA_HARDFLAGS) != (newflags & DMA_HARDFLAGS)) { // something has changed int oldAniX, oldAniY; // objects old animation offsets int newAniX, newAniY; // objects new animation offsets // get objects old animation offsets GetAniOffset(pAniObj->hImg, pAniObj->flags, &oldAniX, &oldAniY); // get objects new animation offsets GetAniOffset(hNewImg, newflags, &newAniX, &newAniY); if (hNewImg) { // get pointer to image const IMAGE *pNewImg = (IMAGE *)LockMem(hNewImg); // setup new shape pAniObj->width = FROM_LE_16(pNewImg->imgWidth); pAniObj->height = FROM_LE_16(pNewImg->imgHeight) & ~C16_FLAG_MASK; newflags &= ~C16_FLAG_MASK; newflags |= FROM_LE_16(pNewImg->imgHeight) & C16_FLAG_MASK; // set objects bitmap definition pAniObj->hBits = FROM_LE_32(pNewImg->hImgBits); } else { // null image pAniObj->width = 0; pAniObj->height = 0; pAniObj->hBits = 0; } // set objects flags and signal a change pAniObj->flags = newflags | DMA_CHANGED; // set objects image pAniObj->hImg = hNewImg; // adjust objects position - subtract new from old for difference pAniObj->xPos += intToFrac(oldAniX - newAniX); pAniObj->yPos += intToFrac(oldAniY - newAniY); } }
void CGEEngine::loadHeroXY() { debugC(1, kCGEDebugEngine, "CGEEngine::loadHeroXY()"); EncryptedStream cf(this, "CGE.HXY"); uint16 x, y; memset(_heroXY, 0, sizeof(_heroXY)); if (!cf.err()) { for (int i = 0; i < kSceneMax; ++i) { cf.read((byte *)&x, 2); cf.read((byte *)&y, 2); _heroXY[i].x = (int16)FROM_LE_16(x); _heroXY[i].y = (int16)FROM_LE_16(y); } } }
double Sound::endiannessHeuristicValue(int16* data, uint32 dataSize, uint32 &maxSamples) { if (!data) return 50000.; // the heuristic value for the wrong endianess is about 21000 (1/3rd of the 16 bits range) double diff_sum = 0.; uint32 cpt = 0; int16 prev_value = (int16)FROM_LE_16(*((uint16 *)(data))); for (uint32 i = 1; i < dataSize && cpt < maxSamples; ++i) { int16 value = (int16)FROM_LE_16(*((uint16 *)(data + i))); if (value != prev_value) { diff_sum += fabs((double)(value - prev_value)); ++cpt; prev_value = value; } } if (cpt == 0) return 50000.; maxSamples = cpt; return diff_sum / cpt; }
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; }
void Disk::openFile(uint8 fileNum) { // Validate that the file number is correct bool isEGA = LureEngine::getReference().isEGA(); if (fileNum > 4) error("Invalid file number specified - %d", fileNum); // Only load up the new file if the current file number has changed if (fileNum == _fileNum) return; // Delete any existing open file handle if (_fileNum != 0xff) delete _fileHandle; _fileNum = fileNum; // Open up the the new file _fileHandle = new Common::File(); char sFilename[10]; if (_fileNum == 0) strcpy(sFilename, SUPPORT_FILENAME); else sprintf(sFilename, "disk%d.%s", _fileNum, isEGA ? "ega" : "vga"); _fileHandle->open(sFilename); if (!_fileHandle->isOpen()) error("Could not open %s", sFilename); char buffer[7]; uint32 bytesRead; // If it's the support file, then move to the correct language area _dataOffset = 0; if (_fileNum == 0) { // Validate overall header _fileHandle->read(buffer, 6); buffer[4] = '\0'; if (strcmp(buffer, SUPPORT_IDENT_STRING) != 0) error("The file %s is not a valid Lure support file", sFilename); // Scan for the correct language block LureLanguage language = LureEngine::getReference().getLureLanguage(); bool foundFlag = false; while (!foundFlag) { _fileHandle->read(buffer, 5); if ((byte)buffer[0] == 0xff) error("Could not find language data in support file"); if ((language == (LureLanguage)buffer[0]) || (language == LANG_UNKNOWN)) { foundFlag = true; _dataOffset = READ_LE_UINT32(&buffer[1]); _fileHandle->seek(_dataOffset); } } } // Validate the header bytesRead = _fileHandle->read(buffer, 6); buffer[6] = '\0'; if (strcmp(buffer, HEADER_IDENT_STRING) != 0) error("The file %s was not a valid VGA file", sFilename); uint16 fileFileNum = _fileHandle->readUint16BE(); if ((fileFileNum != 0) && (fileFileNum != (isEGA ? _fileNum + 4 : _fileNum))) error("The file %s was not the correct file number", sFilename); // Read in the header entries uint32 headerSize = sizeof(FileEntry) * NUM_ENTRIES_IN_HEADER; if (_fileHandle->read(_entries, headerSize) != headerSize) error("The file %s had a corrupted header", sFilename); #ifdef SCUMM_BIG_ENDIAN // Process the read in header list to convert to big endian for (int i = 0; i < NUM_ENTRIES_IN_HEADER; ++i) { _entries[i].id = FROM_LE_16(_entries[i].id); _entries[i].size = FROM_LE_16(_entries[i].size); _entries[i].offset = FROM_LE_16(_entries[i].offset); } #endif }
/** * Initialise a object using a OBJ_INIT structure to supply parameters. * @param pInitTbl Pointer to object initialisation table */ OBJECT *InitObject(const OBJ_INIT *pInitTbl) { // allocate a new object OBJECT *pObj = AllocObject(); // make sure object created assert(pObj != NULL); // set objects shape pObj->hImg = pInitTbl->hObjImg; // set objects ID pObj->oid = pInitTbl->objID; // set objects flags pObj->flags = DMA_CHANGED | pInitTbl->objFlags; // set objects Z position pObj->zPos = pInitTbl->objZ; // get pointer to image if (pInitTbl->hObjImg) { int aniX, aniY; // objects animation offsets PALQ *pPalQ = NULL; // palette queue pointer const IMAGE *pImg = (const IMAGE *)LockMem(pInitTbl->hObjImg); // handle to image if (pImg->hImgPal) { // allocate a palette for this object pPalQ = AllocPalette(FROM_LE_32(pImg->hImgPal)); // make sure palette allocated assert(pPalQ != NULL); } // assign palette to object pObj->pPal = pPalQ; // set objects size pObj->width = FROM_LE_16(pImg->imgWidth); pObj->height = FROM_LE_16(pImg->imgHeight) & ~C16_FLAG_MASK; pObj->flags &= ~C16_FLAG_MASK; pObj->flags |= FROM_LE_16(pImg->imgHeight) & C16_FLAG_MASK; // set objects bitmap definition pObj->hBits = FROM_LE_32(pImg->hImgBits); // get animation offset of object GetAniOffset(pObj->hImg, pInitTbl->objFlags, &aniX, &aniY); // set objects X position - subtract ani offset pObj->xPos = intToFrac(pInitTbl->objX - aniX); // set objects Y position - subtract ani offset pObj->yPos = intToFrac(pInitTbl->objY - aniY); } else { // no image handle - null image // set objects X position pObj->xPos = intToFrac(pInitTbl->objX); // set objects Y position pObj->yPos = intToFrac(pInitTbl->objY); } // return new object return pObj; }
byte *loadVOCFromStream(Common::ReadStream &stream, int &size, int &rate, int &loops, int &begin_loop, int &end_loop) { VocFileHeader fileHeader; if (stream.read(&fileHeader, 8) != 8) goto invalid; if (!memcmp(&fileHeader, "VTLK", 4)) { if (stream.read(&fileHeader, sizeof(VocFileHeader)) != sizeof(VocFileHeader)) goto invalid; } else if (!memcmp(&fileHeader, "Creative", 8)) { if (stream.read(((byte *)&fileHeader) + 8, sizeof(VocFileHeader) - 8) != sizeof(VocFileHeader) - 8) goto invalid; } else { invalid:; warning("loadVOCFromStream: Invalid header"); return NULL; } if (memcmp(fileHeader.desc, "Creative Voice File", 19) != 0) error("loadVOCFromStream: Invalid header"); if (fileHeader.desc[19] != 0x1A) debug(3, "loadVOCFromStream: Partially invalid header"); int32 offset = FROM_LE_16(fileHeader.datablock_offset); int16 version = FROM_LE_16(fileHeader.version); int16 code = FROM_LE_16(fileHeader.id); assert(offset == sizeof(VocFileHeader)); // 0x100 is an invalid VOC version used by German version of DOTT (Disk) and // French version of Simon the Sorcerer 2 (CD) assert(version == 0x010A || version == 0x0114 || version == 0x0100); assert(code == ~version + 0x1234); int len; byte *ret_sound = 0; size = 0; begin_loop = 0; end_loop = 0; while ((code = stream.readByte())) { len = stream.readByte(); len |= stream.readByte() << 8; len |= stream.readByte() << 16; switch(code) { case 1: { int time_constant = stream.readByte(); int packing = stream.readByte(); len -= 2; rate = getSampleRateFromVOCRate(time_constant); debug(9, "VOC Data Block: %d, %d, %d", rate, packing, len); if (packing == 0) { if (size) { ret_sound = (byte *)realloc(ret_sound, size + len); } else { ret_sound = (byte *)malloc(len); } stream.read(ret_sound + size, len); size += len; begin_loop = size; end_loop = size; } else { warning("VOC file packing %d unsupported", packing); } } break; case 6: // begin of loop assert(len == 2); loops = stream.readUint16LE(); break; case 7: // end of loop assert(len == 0); break; default: warning("Invalid code in VOC file : %d", code); return ret_sound; } } debug(4, "VOC Data Size : %d", size); return ret_sound; }
uint16 File::readWord() { uint16 v; read(&v, sizeof(uint16)); return FROM_LE_16(v); }
void RenderManager::readImageToSurface(const Common::String &fileName, Graphics::Surface &destination, bool transposed) { Common::File file; if (!_engine->getSearchManager()->openFile(file, fileName)) { warning("Could not open file %s", fileName.c_str()); return; } // Read the magic number // Some files are true TGA, while others are TGZ uint32 fileType = file.readUint32BE(); uint32 imageWidth; uint32 imageHeight; Image::TGADecoder tga; uint16 *buffer; // All ZVision images are in RGB 555 destination.format = _engine->_resourcePixelFormat; bool isTGZ; // Check for TGZ files if (fileType == MKTAG('T', 'G', 'Z', '\0')) { isTGZ = true; // TGZ files have a header and then Bitmap data that is compressed with LZSS uint32 decompressedSize = file.readSint32LE() / 2; imageWidth = file.readSint32LE(); imageHeight = file.readSint32LE(); LzssReadStream lzssStream(&file); buffer = (uint16 *)(new uint16[decompressedSize]); lzssStream.read(buffer, 2 * decompressedSize); #ifndef SCUMM_LITTLE_ENDIAN for (uint32 i = 0; i < decompressedSize; ++i) buffer[i] = FROM_LE_16(buffer[i]); #endif } else { isTGZ = false; // Reset the cursor file.seek(0); // Decode if (!tga.loadStream(file)) { warning("Error while reading TGA image"); return; } Graphics::Surface tgaSurface = *(tga.getSurface()); imageWidth = tgaSurface.w; imageHeight = tgaSurface.h; buffer = (uint16 *)tgaSurface.getPixels(); } // Flip the width and height if transposed if (transposed) { uint16 temp = imageHeight; imageHeight = imageWidth; imageWidth = temp; } // If the destination internal buffer is the same size as what we're copying into it, // there is no need to free() and re-create if (imageWidth != destination.w || imageHeight != destination.h) { destination.create(imageWidth, imageHeight, _engine->_resourcePixelFormat); } // If transposed, 'un-transpose' the data while copying it to the destination // Otherwise, just do a simple copy if (transposed) { uint16 *dest = (uint16 *)destination.getPixels(); for (uint32 y = 0; y < imageHeight; ++y) { uint32 columnIndex = y * imageWidth; for (uint32 x = 0; x < imageWidth; ++x) { dest[columnIndex + x] = buffer[x * imageHeight + y]; } } } else { memcpy(destination.getPixels(), buffer, imageWidth * imageHeight * destination.format.bytesPerPixel); } // Cleanup if (isTGZ) { delete[] buffer; } else { tga.destroy(); } }
void SegmentMap::findPath(int16 *pointsArray, int16 destX, int16 destY, int16 sourceX, int16 sourceY) { int16 currentRectIndex, destRectIndex; int16 pointsCount; debug(0, "SegmentMap::findPath(fromX: %d; fromY: %d; toX: %d; toY: %d)", sourceX, sourceY, destX, destY); _deadEndPathRectsCount = 0; _closedPathRectsCount = 0; _pathNodesCount = 0; pointsCount = 2; adjustPathPoint(sourceX, sourceY); currentRectIndex = findPathRectAtPoint(sourceX, sourceY); adjustPathPoint(destX, destY); destRectIndex = findPathRectAtPoint(destX, destY); if (currentRectIndex != -1) { if (destRectIndex != currentRectIndex) { while (1) { do { _closedPathRects[_closedPathRectsCount++] = currentRectIndex; currentRectIndex = findNextPathRect(currentRectIndex, destX, destY); _pathNodesCount++; } while (currentRectIndex != -1 && currentRectIndex != destRectIndex); if (currentRectIndex != -1 && currentRectIndex == destRectIndex) break; _deadEndPathRects[_deadEndPathRectsCount++] = _closedPathRects[--_closedPathRectsCount]; _pathNodesCount -= 2; currentRectIndex = _closedPathRects[--_closedPathRectsCount]; } for (int16 i = 0; i < _pathNodesCount; i++) { pointsArray[pointsCount++] = TO_LE_16(_pathNodes[i].y); pointsArray[pointsCount++] = TO_LE_16(_pathNodes[i].x); } } pointsArray[pointsCount++] = TO_LE_16(destY); pointsArray[pointsCount++] = TO_LE_16(destX); pointsArray[0] = 0; pointsArray[1] = TO_LE_16(_pathNodesCount + 1); } debug(0, "SegmentMap::findPath() count = %d", FROM_LE_16(pointsArray[1])); #if 0 // DEBUG: Draw the path we found int sx = sourceX, sy = sourceY; LineData ld; ld.pitch = _vm->_sceneWidth; ld.surf = _vm->_screen->_backScreen; for (int16 i = 0; i < FROM_LE_16(pointsArray[1]) * 2; i+=2) { const int x = FROM_LE_16(pointsArray[3+i]); const int y = FROM_LE_16(pointsArray[2+1]); debug(0, "x = %d; y = %d", x, y); Graphics::drawLine(sx, sy, x, y, 0xFF, plotProc, &ld); sx = x; sy = y; } #endif }
/** * 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; // Fix image header endianess fix_win32_image_header_endian(PE_HEADER(fi->memory)); /* 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); } } /* 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; } fix_win32_image_data_directory(dir); fi->first_resource = fi->memory + dir->virtual_address; return true; } /* other (unknown) header signature was found */ error("%s: not a Windows library", _fileName.c_str()); return false; }
/** * 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); } return memory; }