Page Index Toggle Pages: 1
Topic Tools
Normal Topic Decompress with Java (Read 5157 times)
Sanix
Peon
*
Offline



Posts: 2
Joined: Oct 3rd, 2008
Decompress with Java
Oct 3rd, 2008 at 7:10pm
Post Tools
Hi, I tried to decompress the 3.0 Data Block Header in Java.

But I get the exception "unknown compression method". Now to make sure, that I extracted the correct data:

It's a 1.22 replay with a 1.0 Header. So the 3.0 header starts at 0x44 Bytes. The compressed data length is 2703. So is it correct to decompress all bytes from 0x4C Bytes to 0x4C Bytes to 0x4C Bytes + 2703?
  
Back to top
 
IP Logged
 
Sanix
Peon
*
Offline



Posts: 2
Joined: Oct 3rd, 2008
Re: Decompress with Java
Reply #1 - Oct 4th, 2008 at 6:02pm
Post Tools
Can please anyone confirm, that this is correct? I tried another zlib library and got the same error, so I'm wondering, if I misunderstood the manual.
  
Back to top
 
IP Logged
 
Anomandaris.
Peon
*
Offline



Posts: 1
Joined: Oct 7th, 2008
Re: Decompress with Java
Reply #2 - Oct 7th, 2008 at 10:46pm
Post Tools
Java libraries are ok with decopressing data. I had some problems too, but finally managed to do it. You probably wrongly interpreted Data Block Header

Code
Select All
offset | size/type | Description
-------+-----------+-----------------------------------------------------------
0x0000 |  1  word  | size n of compressed data block (excluding header)
0x0002 |  1  word  | size of decompressed data block (currently 8k)
0x0004 |  1 dword  | unknown (probably checksum)
0x0008 |  n bytes  | compressed data (decompress using zlib)
 


first 2 words and 1 dword (8 bytes in total) doesn't belong to compressed data, you must start decompressing starting from 9th byte. And each block you decompress as separete piece of compressed data.

You can check how I did it in my parser

Code
Select All
package anom.w3ganalizer;

import java.io.IOException;
import java.io.InputStream;
import java.util.zip.DataFormatException;
import java.util.zip.Inflater;
import java.util.zip.ZipException;

/**
 * This is input stream to read packed data in zlib format from replay file.
 * It can read whole packed data from replay file starting from first block header's first byte.
 *
 * @author Anomandaris
 *
 */
public class W3GZLibFilterInputStream extends InputStream {

	private InputStream in;
	private byte[] dData;
	private int position = 0;
	private int cLength;
	private int dLength;
	private long currBlock = 0;
	private long maxBlock;

	/**
	 * Creates new instance of stream, that will read packed data from given source stream
	 * @param in stream with packed data
	 * @param maxBlock number of packed blocks in stream
	 */
	public W3GZLibFilterInputStream(InputStream in, long maxBlock){
		this.in = in;
		this.maxBlock = maxBlock;
	}

	/**
	 * Returns one byte (value 0 - 255) of unpacked data, or -1 if end of stream is reached
	 */
	public int read() throws IOException {
		if(position == 0) {
			if(currBlock == maxBlock) {
				return -1;
			}
			DataParser p = new DataParser(in);
			cLength = p.getWord();				 // reads word from in
			dLength = p.getWord();				// reads word from in
			p.skip(4);							// reads 4 bytes from in
			byte[] cData = new byte[cLength];
			dData = new byte[dLength];
			int l = in.read(cData, 0, cLength);
			if(l != cLength)
				throw new IOException(String.format("Needs to read %d compressed bytes from input, but only %d available", cLength, l));
			Inflater inflater = new Inflater(false);
			inflater.setInput(cData, 0, cLength);
			try {
				l = inflater.inflate(dData, 0, dLength);
			} catch (DataFormatException e) {
				throw new ZipException("Invalid data");
			}
			if(l != dLength)
				throw new ZipException(String.format("Inflated %d bytes instead of %d", l, dLength));
		}
		int ret = dData[position];
		position++;
		if(position == dLength)
			position = 0;
		if(ret < 0)
			ret = 256 + ret;
		return ret;
	}
}
 

  
Back to top
 
IP Logged
 
Serrin
Peon
*
Offline



Posts: 2
Joined: Nov 15th, 2008
Re: Decompress with Java
Reply #3 - Nov 15th, 2008 at 3:12pm
Post Tools
Hi,
I'm currently trying to write a parser myself and i'm a little confused by the length of the compressed data. It should be located at 0x44 bytes, right (latest version wc3 rep file)? But the word there is 0xAC0B, and the next word is 0x0020. That doesn't make sense, does it?
A word is two Bytes here, right? So the target Bytes for the compressed size would be Bytes numero 68 and 69!?
Somehow i think i got wrong  Roll Eyes
  
Back to top
 
IP Logged
 
Serrin
Peon
*
Offline



Posts: 2
Joined: Nov 15th, 2008
Re: Decompress with Java
Reply #4 - Nov 15th, 2008 at 7:38pm
Post Tools
Ah i found the mistake. Didn't know that the right byte of a word corresponds to the "high" value.
  
Back to top
 
IP Logged
 
Page Index Toggle Pages: 1
Topic Tools