144 lines
5.8 KiB
Plaintext
144 lines
5.8 KiB
Plaintext
|
|
|||
|
Here's something that might help you... I wrote it quite fast but it should
|
|||
|
be accurate ;) However, there's probably a lot of stuff here that you don't
|
|||
|
need/understant for now... but keep all this, you'll need it soon ;)
|
|||
|
|
|||
|
--> This is NOT the "official" Tehcnical stuff....
|
|||
|
|
|||
|
File Header:
|
|||
|
|
|||
|
offset type/size comment
|
|||
|
------ --------- ---------------------------------
|
|||
|
0 char[8] Signature: 'ziRCONia'
|
|||
|
|
|||
|
8 word file header size (from offset 10, not counting this
|
|||
|
word)
|
|||
|
10 word version 0xyyzh (x.yy) (displayed in hex. no conversion)
|
|||
|
z: 0 nothing
|
|||
|
1-0eh revision a to n (-may- be useful...)
|
|||
|
0fh Beta
|
|||
|
12 word number of blocks within file
|
|||
|
14 dword total length of unpacked file
|
|||
|
18 dword file offset where is located the "block offset table"
|
|||
|
22 word dummy... must currently be 0ffffH
|
|||
|
|
|||
|
|
|||
|
The block offset table is simply N_of_Block dwords which are the
|
|||
|
absolute position of each block in the file. Each of those blocks have
|
|||
|
the following header:
|
|||
|
|
|||
|
0 dword unpacked size
|
|||
|
4 dword compressed size
|
|||
|
8 dword XOR check (see note below)
|
|||
|
12 word number of "sub-blocks" (nblk)
|
|||
|
14 word flags (see below)
|
|||
|
16 word number of translation table entry } for compression
|
|||
|
18 word start number of bit } don't mind them
|
|||
|
for now...
|
|||
|
20 sub-block[nblk] Sub-blocks of data info.
|
|||
|
|
|||
|
each sub-block has the following info:
|
|||
|
0 dword absolute position in uncompressed file
|
|||
|
4 dword size of uncompressed block
|
|||
|
all "nblk" sub-block info are stored right after the block header.
|
|||
|
|
|||
|
Those small blocks are only non-contiguous blocks of the "same type"
|
|||
|
grouped together within one bigger block for better compression.
|
|||
|
|
|||
|
- XOR check: instead of implementing a CRC, I coded a XOR check.
|
|||
|
How it works: a dword variable is set to 0, and XORed
|
|||
|
with every complete 4 bytes of the original data of the
|
|||
|
"bigblock". Remaining bytes (i.e, size of bigblock is
|
|||
|
not a multiple of 4) are simply ignored. This is only
|
|||
|
to implement a minimal check of destination when
|
|||
|
decompressing.
|
|||
|
|
|||
|
- Flags: this is a 16 bits field:
|
|||
|
|
|||
|
15 14 13 12 11 10 9 8
|
|||
|
<20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ŀ
|
|||
|
<20> 0 <20> 0 <20> 0 <20> 0 <20> 0 <20> 0 <20>Abs16<31> M/S <20>
|
|||
|
<20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|||
|
7 6 5 4 3 2 1 0
|
|||
|
<20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ŀ
|
|||
|
<20> R <20> T y p e <20> R <20> 8/16<31>Delta<74>Comp.<2E>
|
|||
|
<20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|||
|
bits marked as "0" MUST be 0 (they are reserved for future
|
|||
|
extensions...) Every "1" must be considered as invalid or
|
|||
|
unsupported feature (compressed by a newer version of MMCMP)
|
|||
|
bits marked as "R" are reserved (used during compression processing
|
|||
|
and they don't mean much within the file...) No check should be
|
|||
|
performed on those bits.
|
|||
|
|
|||
|
- Comp.: 0: not compressed
|
|||
|
1: compressed
|
|||
|
- Delta: 0: data is not changed
|
|||
|
1: data is Delta (every byte or word is the difference
|
|||
|
between itself and the previous one. First byte or word
|
|||
|
is compared to 0.
|
|||
|
- 8/16: 0: 8 bits compression scheme
|
|||
|
1: 16 bits compression scheme
|
|||
|
- M/S: 0: mono
|
|||
|
1: stereo (not implemented yet) MUST BE 0
|
|||
|
|
|||
|
- Abs16 Whithin compression algorithm, 16 bits samples are
|
|||
|
converted to deltas and transformed a bit so there's
|
|||
|
no negative numbers. However, some trackers already
|
|||
|
convert data to deltas, but there's still the little
|
|||
|
transformation to do.
|
|||
|
0: don't do it
|
|||
|
1: do it
|
|||
|
Note: This bit IS NOT checked if Delta bit is 1, but
|
|||
|
should be 0 in this case. May only be set if
|
|||
|
Delta bit is 0.
|
|||
|
|
|||
|
- Type: This field doesn't really serve any purpose ;) but
|
|||
|
helping identify type of data in this block. There's
|
|||
|
no strict identifier but the following block types are
|
|||
|
used by MMCMP (warning: do not expect the following to
|
|||
|
always be true... data of different types for us (e.g
|
|||
|
instrument header and sample header) may be interpreted
|
|||
|
as the same type of block (they are contiguous, or
|
|||
|
similar, etc...) for better compression.) The three
|
|||
|
bits are stored in the order you would expect (MSB at
|
|||
|
left, LSB at right)
|
|||
|
|
|||
|
0: Module identifier: the firsts bytes of a module
|
|||
|
(this type must NOT be used for anything else...)
|
|||
|
1: Module header: anything useful in the header, which
|
|||
|
is not in block-type 0 (actually not used by MMCMP)
|
|||
|
2: instrument header
|
|||
|
3: sample header
|
|||
|
4: patterns
|
|||
|
5: sample
|
|||
|
6: no definition yet...
|
|||
|
7: remaining (every part of the module that hasn't
|
|||
|
been thrown into the "block list" (i.e probably
|
|||
|
don't fit under any block types...)
|
|||
|
|
|||
|
Note that MMCMP sorting scheme puts block of type 0
|
|||
|
first and type 7 last. This is also some sort of
|
|||
|
priority. As for now, know that block of type 0 is
|
|||
|
UNIQUE and is the FIRST.
|
|||
|
|
|||
|
|
|||
|
Scanning files:
|
|||
|
|
|||
|
1. Check if installed and disable MMTSR
|
|||
|
2. Open module
|
|||
|
3. Check signature. If not 'ziRCONia' jump to 11
|
|||
|
4. read "block offset table" offset field (dword at offset 18)
|
|||
|
(and any other info you would like to read)
|
|||
|
5. jump to this position within the file
|
|||
|
6. read the first entry of the table (position of block 0)
|
|||
|
7. jump to this position within the file
|
|||
|
8. read the block header.
|
|||
|
9. If block-type field is not 0, jump to 6 and read the next entry
|
|||
|
instead. (the first block should be of type 0. If not, there's
|
|||
|
probably no block of this type...)
|
|||
|
10.Read the uncompressed data (it should not have the compressed flag
|
|||
|
set)
|
|||
|
11.reenable MMTSR if installed
|
|||
|
12.Do what you would do with the header info and close module if you
|
|||
|
wish...
|