Welcome, Guest. Please Login
Back to main page
  News:
Welcome to the ShadowFlare's Realm Forums.  New registrations are by request only.  To be considered for a new forum account, send an e-mail with the user name and display name you want and the reason you want to register.
  Home SFRealm HelpSearchLogin  
 
Pages: 1
Send Topic Print
Decompress with Java (Read 4508 times)
Sanix
Peon
*
Offline



Posts: 2

Decompress with Java
Oct 03rd, 2008, 8:10pm
 
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

Re: Decompress with Java
Reply #1 - Oct 4th, 2008, 7:02pm
 
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

Re: Decompress with Java
Reply #2 - Oct 7th, 2008, 11:46pm
 
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:
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:
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

Re: Decompress with Java
Reply #3 - Nov 15th, 2008, 3:12pm
 
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

Re: Decompress with Java
Reply #4 - Nov 15th, 2008, 7:38pm
 
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
Pages: 1
Send Topic Print