Пример #1
0
/**
 * 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;
}
Пример #2
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;
}
Пример #3
0
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
}
Пример #4
0
/**
 * 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);
	}
}
Пример #5
0
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);
		}
	}
}
Пример #6
0
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;
}
Пример #7
0
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;
}
Пример #8
0
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
}
Пример #9
0
/**
 * 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;
}
Пример #10
0
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;
}
Пример #11
0
uint16 File::readWord() {
	uint16 v;
	read(&v, sizeof(uint16));
	return FROM_LE_16(v);
}
Пример #12
0
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();
	}
}
Пример #13
0
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

}
Пример #14
0
/**
 * 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;
}
Пример #15
0
/**
 * 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;
}