WZ

The WZ format is what the MapleStory client uses to store nearly all data, consisting of sound, images, strings, and numbers. It is a proprietary binary format, but it isn't too hard to parse.

= Parsing a WZ File =

Primitive types
The wz data is filled with all sorts of primitives. Here is a guide on how to parse them all.

Integers
All integers are stored using little endian. The low byte is the least significant byte. Signed integers use two's complement. No compression or encryption is used on the integers, unless otherwise specified.

The header

 * A 4 byte string for the ident which is always "PKG1". If a file does not begin with this, you can safely assume that it is not a wz file.
 * An 8 byte unsigned integer specifying the size of the file minus the header size.
 * A 4 byte unsigned integer specifying the size of the header.
 * The rest of the space, from the start of the file to the size of the header, is a null terminated copyright string.

struct header { char ident[4] = "PKG1"; uint64 filesize; uint32 headersize; char copyright[headersize-16]; }

The version
The first two bytes after the header are the encrypted version. The only known way to obtain the version from the encrypted number is to brute force it. Aside from knowing what version the wz file is, the version hash is an extremely useful number as it lets you calculate the offsets of directories and imgs, rather than being forced to read everything sequentially.

Unfortunately, the hashing algorithm is rather poor, so false positives are quite likely. The only way to reliably know for sure is to try parsing the wz file. If something isn't right, then go back and try another version.

Directories
The next region of data is filled with all the directories. The first directory begins immediately after the version. Each directory consists of the following.
 * A compressed int specifying the number of children in the directory. If the number is 0 then you can assume that it indicates another wz file.
 * An array of children of size count, each consisting of the following:
 * A 1 byte unsigned integer indicating the type of the child.
 * If type == 2
 * 4 byte unsigned integer offset
 * Seek to that offset + end of header
 * A new 1 byte unsigned integer to replace the old type
 * An encrypted string for the name of the child
 * Return to your position before the seek
 * If type == 3 or type == 4 (3 means the child is a directory, 4 means the child is a img)
 * An encrypted string for the name of the child
 * If type == 1, OH GOD WHAT IS THIS I DON'T EVEN
 * A compressed int indicating the size of the child
 * A compressed int indicating a checksum of the child
 * An encrypted offset indicating the location of the child