Exemple #1
0
static void input_handle_th(void *p)
{
	char c;
	int b = 0;
	setsockopt(ihpipe[1], SOL_SOCKET, SO_NONBLOCK, &b, sizeof(b));
	while (1) if (read(0, &c, 1) == 1) be_write(ihpipe[1], &c, 1);
}
Exemple #2
0
static void be_write_list(struct be_list *list, FILE *out)
{
	size_t i;
	fputc('l', out);
	for(i = 0; i < list->len; i++) {
		be_write(list->nodes + i, out);
	}
	fputc('e', out);
}
Exemple #3
0
static void be_write_dict(struct be_dict *dict, FILE *out)
{
	fputc('d', out);
	size_t i;
	for(i = 0; i < dict->len; i++) {
		struct be_str *bstr = dict->pairs[i].key;
		be_write_str(bstr, out);
		be_write(dict->pairs[i].val, out);
	}
	fputc('e', out);
}
Exemple #4
0
void chd_file::decompress_v5_map()
{
	// if no offset, we haven't written it yet
	if (m_mapoffset == 0)
	{
		memset(m_rawmap, 0xff, m_rawmap.count());
		return;
	}

	// read the reader
	UINT8 rawbuf[16];
	file_read(m_mapoffset, rawbuf, sizeof(rawbuf));
	UINT32 mapbytes = be_read(&rawbuf[0], 4);
	UINT64 firstoffs = be_read(&rawbuf[4], 6);
	UINT16 mapcrc = be_read(&rawbuf[10], 2);
	UINT8 lengthbits = rawbuf[12];
	UINT8 selfbits = rawbuf[13];
	UINT8 parentbits = rawbuf[14];

	// now read the map
	dynamic_buffer compressed(mapbytes);
	file_read(m_mapoffset + 16, compressed, mapbytes);
	bitstream_in bitbuf(compressed, compressed.count());

	// first decode the compression types
	huffman_decoder<16, 8> decoder;
	huffman_error err = decoder.import_tree_rle(bitbuf);
	if (err != HUFFERR_NONE)
		throw CHDERR_DECOMPRESSION_ERROR;
	UINT8 lastcomp = 0;
	int repcount = 0;
	for (int hunknum = 0; hunknum < m_hunkcount; hunknum++)
	{
		UINT8 *rawmap = &m_rawmap[hunknum * 12];
		if (repcount > 0)
			rawmap[0] = lastcomp, repcount--;
		else
		{
			UINT8 val = decoder.decode_one(bitbuf);
			if (val == COMPRESSION_RLE_SMALL)
				rawmap[0] = lastcomp, repcount = 2 + decoder.decode_one(bitbuf);
			else if (val == COMPRESSION_RLE_LARGE)
				rawmap[0] = lastcomp, repcount = 2 + 16 + (decoder.decode_one(bitbuf) << 4), repcount += decoder.decode_one(bitbuf);
			else
				rawmap[0] = lastcomp = val;
		}
	}

	// then iterate through the hunks and extract the needed data
	UINT64 curoffset = firstoffs;
	UINT32 last_self = 0;
	UINT64 last_parent = 0;
	for (int hunknum = 0; hunknum < m_hunkcount; hunknum++)
	{
		UINT8 *rawmap = &m_rawmap[hunknum * 12];
		UINT64 offset = curoffset;
		UINT32 length = 0;
		UINT16 crc = 0;
		switch (rawmap[0])
		{
			// base types
			case COMPRESSION_TYPE_0:
			case COMPRESSION_TYPE_1:
			case COMPRESSION_TYPE_2:
			case COMPRESSION_TYPE_3:
				curoffset += length = bitbuf.read(lengthbits);
				crc = bitbuf.read(16);
				break;

			case COMPRESSION_NONE:
				curoffset += length = m_hunkbytes;
				crc = bitbuf.read(16);
				break;

			case COMPRESSION_SELF:
				last_self = offset = bitbuf.read(selfbits);
				break;

			case COMPRESSION_PARENT:
				offset = bitbuf.read(parentbits);
				last_parent = offset;
				break;

			// pseudo-types; convert into base types
			case COMPRESSION_SELF_1:
				last_self++;
			case COMPRESSION_SELF_0:
				rawmap[0] = COMPRESSION_SELF;
				offset = last_self;
				break;

			case COMPRESSION_PARENT_SELF:
				rawmap[0] = COMPRESSION_PARENT;
				last_parent = offset = (UINT64(hunknum) * UINT64(m_hunkbytes)) / m_unitbytes;
				break;

			case COMPRESSION_PARENT_1:
				last_parent += m_hunkbytes / m_unitbytes;
			case COMPRESSION_PARENT_0:
				rawmap[0] = COMPRESSION_PARENT;
				offset = last_parent;
				break;
		}
		be_write(&rawmap[1], length, 3);
		be_write(&rawmap[4], offset, 6);
		be_write(&rawmap[10], crc, 2);
	}

	// verify the final CRC
	if (crc16_creator::simple(m_rawmap, m_hunkcount * 12) != mapcrc)
		throw CHDERR_DECOMPRESSION_ERROR;
}
Exemple #5
0
chd_error chd_file::read_hunk(UINT32 hunknum, void *buffer)
{
	// wrap this for clean reporting
	try
	{
		// punt if no file
		if (m_file == NULL)
			throw CHDERR_NOT_OPEN;

		// return an error if out of range
		if (hunknum >= m_hunkcount)
			throw CHDERR_HUNK_OUT_OF_RANGE;

		// get a pointer to the map entry
		UINT64 blockoffs;
		UINT32 blocklen;
		UINT32 blockcrc;
		UINT8 *rawmap;
		UINT8 *dest = reinterpret_cast<UINT8 *>(buffer);
		switch (m_version)
		{
			// v3/v4 map entries
			case 3:
			case 4:
				rawmap = m_rawmap + 16 * hunknum;
				blockoffs = be_read(&rawmap[0], 8);
				blockcrc = be_read(&rawmap[8], 4);
				switch (rawmap[15] & V34_MAP_ENTRY_FLAG_TYPE_MASK)
				{
					case V34_MAP_ENTRY_TYPE_COMPRESSED:
						blocklen = be_read(&rawmap[12], 2) + (rawmap[14] << 16);
						file_read(blockoffs, m_compressed, blocklen);
						m_decompressor[0]->decompress(m_compressed, blocklen, dest, m_hunkbytes);
						if (!(rawmap[15] & V34_MAP_ENTRY_FLAG_NO_CRC) && dest != NULL && crc32_creator::simple(dest, m_hunkbytes) != blockcrc)
							throw CHDERR_DECOMPRESSION_ERROR;
						return CHDERR_NONE;

					case V34_MAP_ENTRY_TYPE_UNCOMPRESSED:
						file_read(blockoffs, dest, m_hunkbytes);
						if (!(rawmap[15] & V34_MAP_ENTRY_FLAG_NO_CRC) && crc32_creator::simple(dest, m_hunkbytes) != blockcrc)
							throw CHDERR_DECOMPRESSION_ERROR;
						return CHDERR_NONE;

					case V34_MAP_ENTRY_TYPE_MINI:
						be_write(dest, blockoffs, 8);
						for (UINT32 bytes = 8; bytes < m_hunkbytes; bytes++)
							dest[bytes] = dest[bytes - 8];
						if (!(rawmap[15] & V34_MAP_ENTRY_FLAG_NO_CRC) && crc32_creator::simple(dest, m_hunkbytes) != blockcrc)
							throw CHDERR_DECOMPRESSION_ERROR;
						return CHDERR_NONE;

					case V34_MAP_ENTRY_TYPE_SELF_HUNK:
						return read_hunk(blockoffs, dest);

					case V34_MAP_ENTRY_TYPE_PARENT_HUNK:
						if (m_parent_missing)
							throw CHDERR_REQUIRES_PARENT;
						return m_parent->read_hunk(blockoffs, dest);
				}
				break;

			// v5 map entries
			case 5:
				rawmap = m_rawmap + m_mapentrybytes * hunknum;

				// uncompressed case
				if (!compressed())
				{
					blockoffs = UINT64(be_read(rawmap, 4)) * UINT64(m_hunkbytes);
					if (blockoffs != 0)
						file_read(blockoffs, dest, m_hunkbytes);
					else if (m_parent_missing)
						throw CHDERR_REQUIRES_PARENT;
					else if (m_parent != NULL)
						m_parent->read_hunk(hunknum, dest);
					else
						memset(dest, 0, m_hunkbytes);
					return CHDERR_NONE;
				}

				// compressed case
				blocklen = be_read(&rawmap[1], 3);
				blockoffs = be_read(&rawmap[4], 6);
				blockcrc = be_read(&rawmap[10], 2);
				switch (rawmap[0])
				{
					case COMPRESSION_TYPE_0:
					case COMPRESSION_TYPE_1:
					case COMPRESSION_TYPE_2:
					case COMPRESSION_TYPE_3:
						file_read(blockoffs, m_compressed, blocklen);
						m_decompressor[rawmap[0]]->decompress(m_compressed, blocklen, dest, m_hunkbytes);
						if (!m_decompressor[rawmap[0]]->lossy() && dest != NULL && crc16_creator::simple(dest, m_hunkbytes) != blockcrc)
							throw CHDERR_DECOMPRESSION_ERROR;
						if (m_decompressor[rawmap[0]]->lossy() && crc16_creator::simple(m_compressed, blocklen) != blockcrc)
							throw CHDERR_DECOMPRESSION_ERROR;
						return CHDERR_NONE;

					case COMPRESSION_NONE:
						file_read(blockoffs, dest, m_hunkbytes);
						if (crc16_creator::simple(dest, m_hunkbytes) != blockcrc)
							throw CHDERR_DECOMPRESSION_ERROR;
						return CHDERR_NONE;

					case COMPRESSION_SELF:
						return read_hunk(blockoffs, dest);

					case COMPRESSION_PARENT:
						if (m_parent_missing)
							throw CHDERR_REQUIRES_PARENT;
						return m_parent->read_bytes(UINT64(blockoffs) * UINT64(m_parent->unit_bytes()), dest, m_hunkbytes);
				}
				break;
		}

		// if we get here, something was wrong
		throw CHDERR_READ_ERROR;
	}

	// just return errors
	catch (chd_error &err)
	{
		return err;
	}
}