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

📄 explode.cpp

📁 魔兽解压DBC的一些功能代码,专门用来分解魔兽客户端所使用的代码
💻 CPP
📖 第 1 页 / 共 2 页
字号:
	mpq_pkzip->extra_bits = (mpq_pkzip->extra_bits - bits) + 8;
	return 0;
}

/*
 *  Decompress the imploded data using coded literals.
 *  Returns: 0x000 - 0x0FF : One byte from compressed file.
 *           0x100 - 0x305 : Copy previous block (0x100 = 1 byte)
 *           0x306         : Out of buffer (?)
 */
static unsigned long libmpq_pkzip_explode_lit(pkzip_data_cmp *mpq_pkzip) {
	unsigned long bits;				/* Number of bits to skip */
	unsigned long value;				/* Position in buffers */

	/* Test the current bit in byte buffer. If is not set, simply return the next byte. */
	if (mpq_pkzip->bit_buf & 1) {

		/* Skip current bit in the buffer. */
		if (libmpq_pkzip_skip_bits(mpq_pkzip, 1)) {
			return 0x306;
		}

		/* The next bits are position in buffers. */
		value = mpq_pkzip->pos2[(mpq_pkzip->bit_buf & 0xFF)];

		/* Get number of bits to skip */
		if (libmpq_pkzip_skip_bits(mpq_pkzip, mpq_pkzip->slen_bits[value])) {
			return 0x306;
		}
		if ((bits = mpq_pkzip->clen_bits[value]) != 0) {
			unsigned long val2 = mpq_pkzip->bit_buf & ((1 << bits) - 1);
			if (libmpq_pkzip_skip_bits(mpq_pkzip, bits)) {
				if ((value + val2) != 0x10E) {
					return 0x306;
				}
			}
			value = mpq_pkzip->len_base[value] + val2;
		}
		return value + 0x100;			/* Return number of bytes to repeat */
	}

	/* Skip one bit */
	if (libmpq_pkzip_skip_bits(mpq_pkzip, 1)) {
		return 0x306;
	}

	/* If the binary compression type, read 8 bits and return them as one byte. */
	if (mpq_pkzip->cmp_type == LIBMPQ_PKZIP_CMP_BINARY) {
		value = mpq_pkzip->bit_buf & 0xFF;
		if (libmpq_pkzip_skip_bits(mpq_pkzip, 8)) {
			return 0x306;
		}
		return value;
	}

	/* When ASCII compression ... */
	if (mpq_pkzip->bit_buf & 0xFF) {
		value = mpq_pkzip->offs_2c34[mpq_pkzip->bit_buf & 0xFF];
		if (value == 0xFF) {
			if (mpq_pkzip->bit_buf & 0x3F) {
				if (libmpq_pkzip_skip_bits(mpq_pkzip, 4)) {
					return 0x306;
				}
				value = mpq_pkzip->offs_2d34[mpq_pkzip->bit_buf & 0xFF];
			} else {
				if (libmpq_pkzip_skip_bits(mpq_pkzip, 6)) {
					return 0x306;
				}
				value = mpq_pkzip->offs_2e34[mpq_pkzip->bit_buf & 0x7F];
			}
		}
	} else {
		if (libmpq_pkzip_skip_bits(mpq_pkzip, 8)) {
			return 0x306;
		}
		value = mpq_pkzip->offs_2eb4[mpq_pkzip->bit_buf & 0xFF];
	}
	return libmpq_pkzip_skip_bits(mpq_pkzip, mpq_pkzip->bits_asc[value]) ? 0x306 : value;
}

/*
 *  Retrieves the number of bytes to move back.
 */
static unsigned long libmpq_pkzip_explode_dist(pkzip_data_cmp *mpq_pkzip, unsigned long length) {
	unsigned long pos  = mpq_pkzip->pos1[(mpq_pkzip->bit_buf & 0xFF)];
	unsigned long skip = mpq_pkzip->dist_bits[pos];	/* Number of bits to skip */

	/* Skip the appropriate number of bits */
	if (libmpq_pkzip_skip_bits(mpq_pkzip, skip) == 1) {
		return 0;
	}
	if (length == 2) {
		pos = (pos << 2) | (mpq_pkzip->bit_buf & 0x03);
		if (libmpq_pkzip_skip_bits(mpq_pkzip, 2) == 1) {
			return 0;
		}
	} else {
		pos = (pos << mpq_pkzip->dsize_bits) | (mpq_pkzip->bit_buf & mpq_pkzip->dsize_mask);

		/* Skip the bits */
		if (libmpq_pkzip_skip_bits(mpq_pkzip, mpq_pkzip->dsize_bits) == 1) {
			return 0;
		}
	}
	return pos + 1;
}

static unsigned long libmpq_pkzip_expand(pkzip_data_cmp *mpq_pkzip) {
	unsigned int copy_bytes;			/* Number of bytes to copy */
	unsigned long one_byte;				/* One byte from compressed file */
	unsigned long result;

	mpq_pkzip->out_pos = 0x1000;			/* Initialize output buffer position */

	/* If end of data or error, terminate decompress */
	while ((result = one_byte = libmpq_pkzip_explode_lit(mpq_pkzip)) < 0x305) {

		/* If one byte is greater than 0x100, means "Repeat n - 0xFE bytes" */
		if (one_byte >= 0x100) {
			unsigned char *source;		/* ECX */
			unsigned char *target;		/* EDX */
			unsigned long copy_length = one_byte - 0xFE;
			unsigned long move_back;

			/* Get length of data to copy */
			if ((move_back = libmpq_pkzip_explode_dist(mpq_pkzip, copy_length)) == 0) {
				result = 0x306;
				break;
			}

			/* Target and source pointer */
			target = &mpq_pkzip->out_buf[mpq_pkzip->out_pos];
			source = target - move_back;
			mpq_pkzip->out_pos += copy_length;
			while (copy_length-- > 0) {
				*target++ = *source++;
			}
		} else {
			mpq_pkzip->out_buf[mpq_pkzip->out_pos++] = (unsigned char)one_byte;
		}

		/*
		 * If number of extracted bytes has reached 1/2 of output buffer,
		 * flush output buffer.
		 */
		if (mpq_pkzip->out_pos >= 0x2000) {

			/* Copy decompressed data into user buffer. */
			copy_bytes = 0x1000;
			mpq_pkzip->write_buf((char *)&mpq_pkzip->out_buf[0x1000], &copy_bytes, mpq_pkzip->param);

			/* If there are some data left, keep them alive */
			memcpy(mpq_pkzip->out_buf, &mpq_pkzip->out_buf[0x1000], mpq_pkzip->out_pos - 0x1000);
			mpq_pkzip->out_pos -= 0x1000;
		}
	}
	copy_bytes = mpq_pkzip->out_pos - 0x1000;
	mpq_pkzip->write_buf((char *)&mpq_pkzip->out_buf[0x1000], &copy_bytes, mpq_pkzip->param);
	return result;
}

/*
 * Main exploding function.
 */
unsigned int libmpq_pkzip_explode(
	unsigned int	(*read_buf)(char *buf, unsigned  int *size, void *param),
	void		(*write_buf)(char *buf, unsigned  int *size, void *param),
	char		*work_buf,
	void		*param) {

	pkzip_data_cmp *mpq_pkzip = (pkzip_data_cmp *)work_buf;

	/* Set the whole work buffer to zeros */
	memset(mpq_pkzip, 0, sizeof(pkzip_data_cmp));

	/* Initialize work struct and load compressed data */
	mpq_pkzip->read_buf   = read_buf;
	mpq_pkzip->write_buf  = write_buf;
	mpq_pkzip->param      = param;
	mpq_pkzip->in_pos     = sizeof(mpq_pkzip->in_buf);
	mpq_pkzip->in_bytes   = mpq_pkzip->read_buf((char *)mpq_pkzip->in_buf, &mpq_pkzip->in_pos, mpq_pkzip->param);
	if (mpq_pkzip->in_bytes <= 4) {
		return LIBMPQ_PKZIP_CMP_BAD_DATA;
	}
	mpq_pkzip->cmp_type   = mpq_pkzip->in_buf[0];	/* Get the compression type */
	mpq_pkzip->dsize_bits = mpq_pkzip->in_buf[1];	/* Get the dictionary size */
	mpq_pkzip->bit_buf    = mpq_pkzip->in_buf[2];	/* Initialize 16-bit bit buffer */
	mpq_pkzip->extra_bits = 0;			/* Extra (over 8) bits */
	mpq_pkzip->in_pos     = 3;			/* Position in input buffer */

	/* Test for the valid dictionary size */
	if (4 > mpq_pkzip->dsize_bits || mpq_pkzip->dsize_bits > 6) {
		return LIBMPQ_PKZIP_CMP_INV_DICTSIZE;
	}
	mpq_pkzip->dsize_mask = 0xFFFF >> (0x10 - mpq_pkzip->dsize_bits);	/* Shifted by 'sar' instruction */
	if (mpq_pkzip->cmp_type != LIBMPQ_PKZIP_CMP_BINARY) {
		if (mpq_pkzip->cmp_type != LIBMPQ_PKZIP_CMP_ASCII) {
			return LIBMPQ_PKZIP_CMP_INV_MODE;
		}
		memcpy(mpq_pkzip->bits_asc, pkzip_bits_asc, sizeof(mpq_pkzip->bits_asc));
		libmpq_pkzip_gen_asc_tabs(mpq_pkzip);
	}
	memcpy(mpq_pkzip->slen_bits, pkzip_slen_bits, sizeof(mpq_pkzip->slen_bits));
	libmpq_pkzip_gen_decode_tabs(0x10, mpq_pkzip->slen_bits, pkzip_len_code, mpq_pkzip->pos2);
	memcpy(mpq_pkzip->clen_bits, pkzip_clen_bits, sizeof(mpq_pkzip->clen_bits));
	memcpy(mpq_pkzip->len_base, pkzip_len_base, sizeof(mpq_pkzip->len_base));
	memcpy(mpq_pkzip->dist_bits, pkzip_dist_bits, sizeof(mpq_pkzip->dist_bits));
	libmpq_pkzip_gen_decode_tabs(0x40, mpq_pkzip->dist_bits, pkzip_dist_code, mpq_pkzip->pos1);
	if (libmpq_pkzip_expand(mpq_pkzip) != 0x306) {
		return LIBMPQ_PKZIP_CMP_NO_ERROR;
	}
	return LIBMPQ_PKZIP_CMP_ABORT;
}

⌨️ 快捷键说明

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