DAT MANAGER v.4

I use custom bundle files to store resources for games and programs
(like SSSLIDE.DAT in Sexy Smart Slide, TJAW!3.DAT in the Jaw remake,
PANDA.DAT in Panda Blast!) They are VERY similar to old Apogee's CMP
files or Build engine's GRP files. This program allows you to manage
these resources.

USAGE: DATMNGR.EXE <dat> <mode> <mask1> <mask2> ... <maskN>

<dat>  Is the bundle file to manipulate (most operation modes
       require the bundle file to exist)
<mode> Is the operation mode, it can be one of the following:
       -L  Lists chunks contained in the specified DAT file. You may
           follow this operation by a mask to only display certain
           files. To save the list in a file, add "> myfile.txt"
           right after the last parameter.
       -X  Extracts the specified chunks from the specified DAT file.
           Note that files are copied and won't be removed from the
           bundle.
       -D  Deletes the specified chunks from the specified DAT file.
           The bundle is deleted if it doesn't contain any file after
           this operation.
       -A  Adds (or replaces) chunks in the specified DAT file. If
           the bundle file doesn't exist, one will be created.
<mask> Is a file mask (straight filename or wildcards) to extract,
       add, delete or list, depending on the selected operation mode.
       File names must be at most 12 characters long and their
       extension must be included. Each filename is separated by a
       simple space. You may use lists of files by preceding the file
       name with "@" (each line in that file must be a file name,
       masks are not supported in that mode.)


== Bundle files structure ==

The file starts with a 16-byte long header:
 4  CHAR[4]   Magic       Must be "BNDL" (or 0x4C444E42 as a 32-bit
                          integer)
 4  INT32     numChunks   Number of chunks contained, at least 1
 4  INT32     reservedA   Must remain empty (0x00000000)
 4  INT32     reservedB   Must remain empty (0x00000000)

A chunk directory follows right after the header. Each entry in the
directory is 16-byte long. Read numChunks entries:
12  CHAR[12]  chunkName   Name of the chunk, padded with space
 4  INT32     chunkSize   Size of the chunk, in bytes

The rest of the file is each chunk, stored contiguously, in the exact
same order as they appear in the directory. To compute the offset of
a given chunk, find the location of the 1st byte of information of
the 1st chunk:

baseOffset = 1 + 16 + (16 * numChunks)
fileOffset = baseOffset

Then, add the length of each previous chunk to the count:

fileOffset = fileOffset + chunkSize

Note: unlike C, in QuickBASIC, the very 1st byte of information of a
file is located at 1, not 0. This is why baseOffset starts at 1 (plus
header size, plus directory size). CHAR[X] must be understood as
STRING * X, and INT32 must be understood as LONG in QuickBASIC.


== Notes about the source ==

Feel free to modify the source to suit your needs. Note that this
program is not 100% safe (there's no overwrite warning).

The most "interesting" aspect of the program is the way the I/O
overhead is reduced by accessing variable-length bytes of
information at once, depending on what remains to be read/written,
the wildcard function is also somewhat interesting.

- Mike Hawk