⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 common.cpp

📁 A*算法 A*算法 A*算法 A*算法A*算法A*算法
💻 CPP
📖 第 1 页 / 共 2 页
字号:
			}
		}
		mpq_b->filepos += mpq_a->mpqpos;
	}

	return LIBMPQ_TOOLS_SUCCESS;
}

int libmpq_file_read_block(mpq_archive *mpq_a, mpq_file *mpq_f, unsigned int blockpos, char *buffer, unsigned int blockbytes) {
	unsigned char *tempbuf = NULL;			/* Buffer for reading compressed data from the file */
	unsigned int readpos = 0;				/* Reading position from the file */
	unsigned int toread = 0;			/* Number of bytes to read */
	unsigned int blocknum = 0;				/* Block number (needed for decrypt) */
	unsigned int bytesread = 0;			/* Total number of bytes read */
	unsigned int nblocks = 0;				/* Number of blocks to load */
	unsigned int i = 0;

	/* Test parameters. Block position and block size must be block-aligned, block size nonzero */
	if ((blockpos & (mpq_a->blocksize - 1)) || blockbytes == 0) {
		return 0;
	}

	/* Check the end of file */
	if ((blockpos + blockbytes) > mpq_f->mpq_b->fsize) {
		blockbytes = mpq_f->mpq_b->fsize - blockpos;
	}
	blocknum = blockpos   / mpq_a->blocksize;
	nblocks  = blockbytes / mpq_a->blocksize;
	if (blockbytes % mpq_a->blocksize) {
		nblocks++;
	}

	/* If file has variable block positions, we have to load them */
	if ((mpq_f->mpq_b->flags & LIBMPQ_FILE_COMPRESSED) && mpq_f->blockposloaded == FALSE) {
		unsigned int nread;

		if (mpq_f->mpq_b->filepos != mpq_a->filepos) {
			lseek(mpq_a->fd, mpq_f->mpq_b->filepos, SEEK_SET);
		}

		/* Read block positions from begin of file. */
		nread = (mpq_f->nblocks + 1) * sizeof(int);
		nread = read(mpq_a->fd, mpq_f->blockpos, nread);

		/*
		//If the archive is protected some way, perform additional check
		//Sometimes, the file appears not to be encrypted, but it is.
		if (mpq_f->blockpos[0] != nread) {
			mpq_f->mpq_b->flags |= LIBMPQ_FILE_ENCRYPTED;
		}

		// Decrypt loaded block positions if necessary
		if (mpq_f->mpq_b->flags & LIBMPQ_FILE_ENCRYPTED) {

			// If we don't know the file seed, try to find it.
			if (mpq_f->seed == 0) {
				mpq_f->seed = libmpq_detect_fileseed(mpq_a, mpq_f->blockpos, nread);
			}

			// If we don't know the file seed, sorry but we cannot extract the file.
			if (mpq_f->seed == 0) {
				return 0;
			}

			// Decrypt block positions
			libmpq_decrypt_block(mpq_a, mpq_f->blockpos, nread, mpq_f->seed - 1);

			// Check if the block positions are correctly decrypted
			// I don't know why, but sometimes it will result invalid
			// block positions on some files.
			if (mpq_f->blockpos[0] != nread) {

				// * Try once again to detect file seed and decrypt the blocks
				lseek(mpq_a->fd, mpq_f->mpq_b->filepos, SEEK_SET);
				nread = read(mpq_a->fd, mpq_f->blockpos, (mpq_f->nblocks + 1) * sizeof(int));
				mpq_f->seed = libmpq_detect_fileseed(mpq_a, mpq_f->blockpos, nread);
				libmpq_decrypt_block(mpq_a, mpq_f->blockpos, nread, mpq_f->seed - 1);

				// Check if the block positions are correctly decrypted.
				if (mpq_f->blockpos[0] != nread) {
					return 0;
				}
			}
		}
		&/

		/* Update mpq_f's variables */
		mpq_f->blockposloaded = TRUE;
		mpq_a->filepos        = mpq_f->mpq_b->filepos + nread;
	}

	/* Get file position and number of bytes to read */
	readpos = blockpos;
	toread  = blockbytes;

	if (mpq_f->mpq_b->flags & LIBMPQ_FILE_COMPRESSED) {
		readpos = mpq_f->blockpos[blocknum];
		toread  = mpq_f->blockpos[blocknum + nblocks] - readpos;
	}
	readpos += mpq_f->mpq_b->filepos;

	/* Get work buffer for store read data */
	if (mpq_f->mpq_b->flags & LIBMPQ_FILE_COMPRESSED) {
		if ((tempbuf = (unsigned char*)malloc(toread)) == NULL) {
			/* Hmmm... We should add a better error handling here :) */
			return 0;
		}
	}

	/* Set file pointer, if necessary. */
	if (mpq_a->filepos != readpos) {
		mpq_a->filepos = lseek(mpq_a->fd, readpos, SEEK_SET);
	}

	/* 15018F87 - Read all requested blocks. */
	bytesread = read(mpq_a->fd, tempbuf, toread);
	mpq_a->filepos = readpos + bytesread;

	/* Block processing part. */
	unsigned int blockstart = 0;			/* Index of block start in work buffer. */
	unsigned int blocksize  = min(blockbytes, mpq_a->blocksize);
	unsigned int index      = blocknum;		/* Current block index. */
	bytesread = 0;					/* Clear read byte counter */

	/* Walk through all blocks. */
	for (i = 0; i < nblocks; i++, index++) {
		int outlength = mpq_a->blocksize;

		if ((mpq_f->mpq_b->flags & (LIBMPQ_FILE_COMPRESS_PKWARE|LIBMPQ_FILE_COMPRESS_MULTI)) == 0 ) {
			memcpy(buffer, tempbuf+blockstart, blocksize);
		}

		/* Get current block length */
		if (mpq_f->mpq_b->flags & LIBMPQ_FILE_COMPRESSED) {
			blocksize = mpq_f->blockpos[index + 1] - mpq_f->blockpos[index];
		}

		/* If block is encrypted, we have to decrypt it. */
		if (mpq_f->mpq_b->flags & LIBMPQ_FILE_ENCRYPTED) {
			if (mpq_f->seed == 0) {
				return 0;
			}
			libmpq_decrypt_block(mpq_a, (unsigned int *)&tempbuf[blockstart], blocksize, mpq_f->seed + index);
		}

		/*
		 *  If the block is really compressed, recompress it.
		 *  WARNING: Some block may not be compressed, it can
		 *  only be determined by comparing uncompressed and
		 *  compressed size!
		 */
		if (blocksize < blockbytes) {

			/* Is the file compressed with PKWARE Data Compression Library? */
			if (mpq_f->mpq_b->flags & LIBMPQ_FILE_COMPRESS_PKWARE) {
				libmpq_pkzip_decompress(buffer, &outlength, (char*)&tempbuf[blockstart], blocksize);
			}

			/*
			 *  Is it a file compressed by Blizzard's multiple compression ?
			 *  Note that Storm.dll v 1.0.9 distributed with Warcraft III
			 *  passes the full path name of the opened archive as the new
			 *  last parameter.
			 */
			if (mpq_f->mpq_b->flags & LIBMPQ_FILE_COMPRESS_MULTI) {
				libmpq_multi_decompress(buffer, &outlength, (char*)&tempbuf[blockstart], blocksize);
			}
			bytesread += outlength;
			buffer    += outlength;
		} else {
			memcpy(buffer, tempbuf, blocksize);
			bytesread += blocksize;
			buffer    += blocksize;
		}
		blockstart += blocksize;
	}

	/* Delete input buffer, if necessary. */
	if (mpq_f->mpq_b->flags & LIBMPQ_FILE_COMPRESSED) {
		free(tempbuf);
	}
	return bytesread;
}

int libmpq_file_read_file(mpq_archive *mpq_a, mpq_file *mpq_f, unsigned int filepos, char *buffer, unsigned int toread) {
	unsigned int bytesread = 0;			/* Number of bytes read from the file */
	unsigned int blockpos;				/* Position in the file aligned to the whole blocks */
	unsigned int loaded = 0;

	/* File position is greater or equal to file size? */
	if (filepos >= mpq_f->mpq_b->fsize) {
		return 0;
	}

	/* If to few bytes in the file remaining, cut them */
	if ((mpq_f->mpq_b->fsize - filepos) < toread) {
		toread = (mpq_f->mpq_b->fsize - filepos);
	}

	/* Block position in the file */
	blockpos = filepos & ~(mpq_a->blocksize - 1);

	/*
	 *  Load the first block, if noncomplete. It may be loaded in the cache buffer.
	 *  We have to check if this block is loaded. If not, load it.
	 */
	if ((filepos % mpq_a->blocksize) != 0) {
		/* Number of bytes remaining in the buffer */
		unsigned int tocopy;
		unsigned int loaded = mpq_a->blocksize;

		/* Check if data are loaded in the cache */
		if (mpq_f->accessed == FALSE || blockpos != mpq_a->blockpos) {   

			/* Load one MPQ block into archive buffer */
			loaded = libmpq_file_read_block(mpq_a, mpq_f, blockpos, (char*)mpq_a->blockbuf, mpq_a->blocksize);
			if (loaded == 0) {
				return 0;
			}

			/* Save lastly accessed file and block position for later use */
			mpq_f->accessed = TRUE;
			mpq_a->blockpos = blockpos;
			mpq_a->bufpos   = filepos % mpq_a->blocksize;
		}
		tocopy = loaded - mpq_a->bufpos;
		if (tocopy > toread) {
			tocopy = toread;
		}

		/* Copy data from block buffer into target buffer */
		memcpy(buffer, mpq_a->blockbuf + mpq_a->bufpos, tocopy);

		/* Update pointers */
		toread        -= tocopy;
		bytesread     += tocopy;
		buffer        += tocopy;
		blockpos      += mpq_a->blocksize;
		mpq_a->bufpos += tocopy;

		/* If all, return. */
		if (toread == 0) {
			return bytesread;
		}
	}

	/* Load the whole ("middle") blocks only if there are more or equal one block */
	if (toread > mpq_a->blocksize) {
		unsigned int blockbytes = toread & ~(mpq_a->blocksize - 1);
		loaded = libmpq_file_read_block(mpq_a, mpq_f, blockpos, buffer, blockbytes);
		if (loaded == 0) {
			return 0;
		}

		/* Update pointers */
		toread    -= loaded;
		bytesread += loaded;
		buffer    += loaded;
		blockpos  += loaded;

		/* If all, return. */
		if (toread == 0) {
			return bytesread;
		}
	}

	/* Load the terminating block */
	if (toread > 0) {
		unsigned int tocopy = mpq_a->blocksize;

		/* Check if data are loaded in the cache */
		if (mpq_f->accessed == FALSE || blockpos != mpq_a->blockpos) {

			/* Load one MPQ block into archive buffer */
			tocopy = libmpq_file_read_block(mpq_a, mpq_f, blockpos, (char*)mpq_a->blockbuf, mpq_a->blocksize);
			if (tocopy == 0) {
				return 0;
			}

			/* Save lastly accessed file and block position for later use */
			mpq_f->accessed = TRUE;
			mpq_a->blockpos = blockpos;
		}
		mpq_a->bufpos  = 0;

		/* Check number of bytes read */
		if (tocopy > toread) {
			tocopy = toread;
		}

		memcpy(buffer, mpq_a->blockbuf, tocopy);
		bytesread     += tocopy;
		mpq_a->bufpos  = tocopy;
	}

	/* Return what we've read */
	return bytesread;
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -