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

📄 huffman.cpp

📁 魔兽解压DBC的一些功能代码,专门用来分解魔兽客户端所使用的代码
💻 CPP
📖 第 1 页 / 共 3 页
字号:
			p_prev = PTR_NOT(p_prev);
		} else {
			p_prev += (p_item1 - p_item1->next->prev);
		}

		p_prev->next = p_next;
		p_next->prev = p_prev;
		p_item1->next = NULL;
		p_item1->prev = NULL;
	}
	pp_item = &ht->first;				/* ESI */
	if (value > 1) {

		/* ECX = ht->first->next; */
		p_item1->next = *pp_item;
		p_item1->prev = (*pp_item)->prev;

		(*pp_item)->prev = p_item2;
		*pp_item = p_item1;

		p_item2->parent = NULL;
		p_item2->child  = NULL;
	} else {
		p_item1->next = (struct huffman_tree_item *)pp_item;
		p_item1->prev = pp_item[1];
		/* EDI = ht->item305C; */
		p_prev = pp_item[1];			/* ECX */
		if (p_prev <= 0) {
			p_prev = PTR_NOT(p_prev);
			p_prev->next = p_item1;
			p_prev->prev = p_item2;

			p_item2->parent = NULL;
			p_item2->child  = NULL;
		} else {
			if (PTR_INT(ht->item305C) < 0) {
				p_prev += (struct huffman_tree_item *)pp_item - (*pp_item)->prev;
			} else {
				p_prev += PTR_INT(ht->item305C);
			}

			p_prev->next    = p_item1;
			pp_item[1]      = p_item2;
			p_item2->parent = NULL;
			p_item2->child  = NULL;
		}
	}
	return p_item2;
}

static void libmpq_huff_call1500E820(struct huffman_tree *ht, struct huffman_tree_item *p_item) {
	struct huffman_tree_item *p_item1;		/* EDI */
	struct huffman_tree_item *p_item2 = NULL;	/* EAX */
	struct huffman_tree_item *p_item3;		/* EDX */
	struct huffman_tree_item *p_prev;		/* EBX */

	for (; p_item != NULL; p_item = p_item->parent) {
		p_item->byte_value++;

		for (p_item1 = p_item; ; p_item1 = p_prev) {
			p_prev = p_item1->prev;
			if (PTR_INT(p_prev) <= 0) {
				p_prev = NULL;
				break;
			}
			if (p_prev->byte_value >= p_item->byte_value) {
				break;
			}
		}

		if (p_item1 == p_item) {
			continue;
		}

		if (p_item1->next != NULL) {
			p_item2 = libmpq_huff_get_prev_item(p_item1, -1);
			p_item2->next = p_item1->next;
			p_item1->next->prev = p_item1->prev;
			p_item1->next = NULL;
			p_item1->prev = NULL;
		}
		p_item2 = p_item->next;
		p_item1->next = p_item2;
		p_item1->prev = p_item2->prev;
		p_item2->prev = p_item1;
		p_item->next = p_item1;
		if ((p_item2 = p_item1) != NULL) {
			p_item2 = libmpq_huff_get_prev_item(p_item, -1);
			p_item2->next = p_item->next;
			p_item->next->prev = p_item->prev;
			p_item->next = NULL;
			p_item->prev = NULL;
		}

		if (p_prev == NULL) {
			p_prev = PTR_PTR(&ht->first);
		}
		p_item2       = p_prev->next;
		p_item->next  = p_item2;
		p_item->prev  = p_item2->prev;
		p_item2->prev = p_item;
		p_prev->next  = p_item;

		p_item3 = p_item1->parent->child;
		p_item2 = p_item->parent;
		if (p_item2->child == p_item) {
			p_item2->child = p_item1;
		}

		if (p_item3 == p_item1) {
			p_item1->parent->child = p_item;
		}

		p_item2 = p_item->parent;
		p_item->parent  = p_item1->parent;
		p_item1->parent = p_item2;
		ht->offs0004++;
	}
}

int libmpq_huff_do_decompress(struct huffman_tree *ht, struct huffman_input_stream *is, unsigned char *out_buf, unsigned int out_length) {
	unsigned int n8bits;				/* 8 bits loaded from input stream */
	unsigned int n7bits;				/* 7 bits loaded from input stream */
	unsigned int found;				/* Thats needed to replace the goto stuff from original source :) */
	unsigned int dcmp_byte = 0;
	unsigned long bit_count;
	struct huffman_decompress *qd;
	unsigned int has_qd;				/* Can we use quick decompression? */
	struct huffman_tree_item *p_item1;
	struct huffman_tree_item *p_item2;
	unsigned char *out_pos = out_buf;

	/* Test the output length. Must not be non zero. */
	if (out_length == 0) {
		return 0;
	}

	/* Get the compression type from the input stream. */
	n8bits = libmpq_huff_get_8bits(is);

	/* Build the Huffman tree */
	libmpq_huff_build_tree(ht, n8bits);
	ht->cmp0 = (n8bits == 0) ? TRUE : FALSE;

	for(;;) {
		n7bits = libmpq_huff_get_7bits(is);	/* Get 7 bits from input stream */

		/*
		 * Try to use quick decompression. Check huffman_decompress array for corresponding item.
		 * If found, use the result byte instead.
		 */
		qd = &ht->qd3474[n7bits];

		/* If there is a quick-pass possible (ebx) */
		has_qd = (qd->offs00 >= ht->offs0004) ? TRUE : FALSE;

		/* If we can use quick decompress, use it. */
		if (has_qd) {
			found = 0;
			if (qd->bits > 7) {
				is->bit_buf >>= 7;
				is->bits -= 7;
				p_item1 = qd->p_item;
				found = 1;
			}
			if (found == 0) {
				is->bit_buf >>= qd->bits;
				is->bits     -= qd->bits;
				dcmp_byte     = qd->dcmp_byte;
			}
		} else {
			found = 1;
			p_item1 = ht->first->next->prev;
			if (PTR_INT(p_item1) <= 0) {
				p_item1 = NULL;
			}
		}

		if (found == 1) {
			bit_count = 0;
			p_item2 = NULL;
			do {
				p_item1 = p_item1->child;	/* Move down by one level */
				if (libmpq_huff_get_bit(is)) {	/* If current bit is set, move to previous */
					p_item1 = p_item1->prev;
				}
				if (++bit_count == 7) {		/* If we are at 7th bit, save current huffman tree item. */
					p_item2 = p_item1;
				}
			} while (p_item1->child != NULL);	/* Walk until tree has no deeper level */

			if (has_qd == FALSE) {
				if (bit_count > 7) {
					qd->offs00 = ht->offs0004;
					qd->bits   = bit_count;
					qd->p_item = p_item2;
				} else {
					unsigned long index = n7bits & (0xFFFFFFFF >> (32 - bit_count));
					unsigned long add   = (1 << bit_count);

					for (qd = &ht->qd3474[index]; index <= 0x7F; index += add, qd += add) {
						qd->offs00    = ht->offs0004;
						qd->bits      = bit_count;
						qd->dcmp_byte = p_item1->dcmp_byte;
					}
				}
			}
			dcmp_byte = p_item1->dcmp_byte;
		}

		if (dcmp_byte == 0x101)	{		/* Huffman tree needs to be modified */
			n8bits  = libmpq_huff_get_8bits(is);
			p_item1 = (ht->last <= 0) ? NULL : ht->last;

			p_item2 = libmpq_huff_call1500E740(ht, 1);
			p_item2->parent     = p_item1;
			p_item2->dcmp_byte  = p_item1->dcmp_byte;
			p_item2->byte_value = p_item1->byte_value;
			ht->items306C[p_item2->dcmp_byte] = p_item2;

			p_item2 = libmpq_huff_call1500E740(ht, 1);
			p_item2->parent     = p_item1;
			p_item2->dcmp_byte  = n8bits;
			p_item2->byte_value = 0;
			ht->items306C[p_item2->dcmp_byte] = p_item2;

			p_item1->child = p_item2;
			libmpq_huff_call1500E820(ht, p_item2);
			if (ht->cmp0 == 0) {
				libmpq_huff_call1500E820(ht, ht->items306C[n8bits]);
			}
			dcmp_byte = n8bits;
		}

		if (dcmp_byte == 0x100) {
			break;
		}

		*out_pos++ = (unsigned char)dcmp_byte;
		if (--out_length == 0) {
			break;
		}
		if (ht->cmp0) {
			libmpq_huff_call1500E820(ht, ht->items306C[dcmp_byte]);
		}
	}
	return (out_pos - out_buf);
}

int libmpq_huff_init_tree(struct huffman_tree *ht, struct huffman_tree_item *hi, unsigned int cmp) {
	int count;

	/* Clear links for all the items in the tree */
	for (hi = ht->items0008, count = 0x203; count != 0; hi++, count--) {
		hi->next = hi->prev = NULL;
	}

	ht->item3050 = NULL;
	ht->item3054 = PTR_PTR(&ht->item3054);
	ht->item3058 = PTR_NOT(ht->item3054);

	ht->item305C = NULL;
	ht->first    = PTR_PTR(&ht->first);
	ht->last     = PTR_NOT(ht->first);

	ht->offs0004 = 1;
	ht->items    = 0;

	/* Clear all huffman_decompress items. Do this only if preparing for decompression */
	if (cmp == LIBMPQ_HUFF_DECOMPRESS) {
		for (count = 0; count < sizeof(ht->qd3474) / sizeof(struct huffman_decompress); count++) {
			ht->qd3474[count].offs00 = 0;
		}
	}

    return 0;
}

⌨️ 快捷键说明

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