Skip to content

Command Line Usage

Charlotte Koch edited this page Jul 18, 2020 · 14 revisions

This article describes how to use the various command line tools which Luna Purpura provides.

  • clu
  • prx
  • mmfw
  • tools/clu2png
  • xpk
  • tools/fakesqs2

clu

The clu program reads CLU files, which are color lookup tables. The tool doesn't do anything except list each of the colors in the table. The program really ought to let you convert a CLU to a PNG image, but as of this writing, that's taken care of by the tools/clu2png Ruby script for now.

$ ./build/src/clu/clu ./zz-tricky/Scene2/\!Scene2.CLU  2>/dev/null | head
========================================
<255,255,255>
<128,0,0>
<0,128,0>
<128,128,0>
<0,0,128>
<128,0,128>
<0,128,128>
<128,128,128>
<253,253,253>

Every CLU file specifies exactly 256 colors.


prx

The prx tool reads PRX archives. It currently does NOT understand PRD/PRS archives. You can use it to list the individual members of an archive or to extract all members, or a single member.

prx: usage: prx [options ...] [file]
	prx -t <file>                                      List members
	prx -x [-v] [-o <path>] -n <ID> <file>             Extract a single member
	prx -x [-v] [-o <path>] -f <TYPE> -r <RID> <file>  Extract a single member by RID
	prx -x [-v] -a <file>                              Extract all members
	prx -h                                             Show this help message

The -t option indicates you want to list all the members of the PRX archive.

$ ./build/src/prx/prx -t ./data/tricky/Credits.PRX
>> 3 entries:
1     !Credits          CLU   64000   2056
2     !Credits          DIB   64000   1082
3    credit            SMF   64000   3845087

Each row represents a single member in the archive. The columns are, from left to right: "internal ID," filename, file type, "resource ID," and finally the file size in bytes.

If you want to extract a single member from an archive, you have two options. You may either refer to the desired member by its "internal" ID, or you may use its "resource ID" (or RID).

Extract via internal ID. prx -x -n <ID> <file>. -x indicates you want to extract, and -n <ID> signifies your intention to extract only a specific member. The number should be the "internal ID" of the asset, that is, the number in the first column.

Extract via resource ID (RID). prx -x -f <TYPE> -r <RID> <file>. Resource IDs are not globally unique across all resources, instead they are "namespaced" by filetype. Therefore, you must provide a 3-letter TYPE as well as a numerical resource ID (the value in the third column of the listing).

By default, the name of the extracted file is based on what is stored inside the archive. (To avoid writing duplicate files, the default filename also embeds member's RID.) However, you may extract the member to a location of your choosing with the -o <path> option. If the specified path is - (a single dash), then the member will be written to the standard output.

If you want to extract all members from the given archive, pass the -a option alongside -x.

If you pass the -v ("verbose") option to an extract command, then a message is printed for each member as they are extracted.


mmfw

The mmfw reads the various kinds of MMFW archives. MMFW archives usually have the following file extensions: MMA ("MMFW Sounds"), MMF ("MMFW Films"), and MMP ("MMFW Pictures"). These are in fact different file formats (because each one stores different kinds of metadata) but they're mostly the same and therefore only 1 tool is needed to extract files from any of them.

mmfw: usage: mmfw [options ...] [file]
	mmfw -t <file>                List archive members
	mmfw -x [-v] -a <file>        Extract all members
	mmfw -x [-v] -n <id> <file>   Extract a single member

The -t option indicates you want to list all members of the archive.

$ ./build/src/mmfw/mmfw -t ./MAKER/Comics.MMF 
mmfw: "Films" MMFW archive with 7 members
0       presents.flm                      3552
1       ramCredits.flm                    646588
2       ramFlash.flm                      7238060
3       ramIntro.flm                      7793948
4       ramTitle.flm                      21813148
5       IbsLogo.flm                       22949984
6       PMsplash.flm                      24137272

Each row represents a single member in the archive. The columns are, from left to right: the ID, filename, and its internal offset.

If you want to extract a single member from the archive, you will need to consult its ID (above) and use this number for the -n <ID> option in mmfw -x -n <ID>. Otherwise, use -a in place of -n <ID> to signify your intention to extract all members into the current directory.

While extracting, you may enable verbose mode with -v, which will write a status message to stderr as each member is extracted.


xpk

The xpk tool tries to decode XPK graphics. Note that a single XPK file can define multiple images (e.g. individual frames in an animation) but as of this writing, xpk will only try to decode the first image.

xpk: usage: xpk [-h] [-p] -c clu -o output file

XPK graphics do not store color information directly, they only store indices into a color lookup table, or CLU. Therefore, you MUST provide the path to a CLU file in order to decode an XPK. You'll know which CLU to use because (typically) a single one can be found in each PRX (or PRS) archive. IDPalette.CLU or _IDGlobal.CLU will be used for anything that's contained in a student's locker.

By default, xpk will write raw RGBA samples (24 bits per pixel). GraphicsMagick (and/or ImageMagick) will allow you to do interesting things with them, but you'll need to pay attention to the width and height of the image. You'll need GraphicsMagick's -depth and -size options like so:

$ ./build/src/xpk/xpk -c tricky/IDGlobal/IDPalette.CLU -o /tmp/MAVglasses_01_H.rgba tricky/IDL/Mavi/MAVglasses_01_H.XPK 
1 entry(ies):
	XPKEntry offset=36 dimensions=106x73 pos=188x362

$ gm convert -depth 8 -size 106x73 rgba:/tmp/MAVglasses_01_H.rgba [output_options ...] <outfile>

If PNG support is present (CMake option LUNAPURPURA_PNG_SUPPORT, enabled by default) then xpk gains support for the -p option. When enabled, -p will generate a PNG image instead of raw RGBA samples.

$ ./build/src/xpk/xpk -c tricky/IDGlobal/IDPalette.CLU -p -o /tmp/MAVglasses_01_H.png tricky/IDL/Mavi/MAVglasses_01_H.XPK 

tools/fakesqs2

SQS2 compression is unknown to FFmpeg, VLC, vgmstream, and, well, virtually all audio software ever. We'll need to reverse engineer it. However, it turns out that the far more popular, well-understood compression scheme "SDX2" is a fairly close approximation. fakesqs2 is a Ruby script which "patches" a AIFF-C file with SQS2 compression and writes a new file which pretends to be encoded with SDX2 compression. This allows the most of the audio for most of the Rockett titles to be audible, but note that it's heavily distorted.

usage: fakesqs2 [options ...] file
    -i, --in-place                   overwrite input file
    -o, --outfile PATH               path to write new file

You can safely use fakesqs2 on AIFF files, and AIFF-C files which do not use SQS2 compression. A copy of the original file will be generated instead.

By the way, you can install the sox software and use the soxi tool to quickly determine whether file is SQS2-ified or not:

$ soxi D1TrailerBox.Aif 

Input File     : 'D1TrailerBox.Aif'
Channels       : 1
Sample Rate    : 22050
Precision      : 16-bit
Duration       : 00:00:00.28 = 6208 samples ~ 21.1156 CDDA sectors
File Size      : 12.5k
Bit Rate       : 355k
Sample Encoding: 16-bit Signed Integer PCM

$ soxi marquee.Aif 
soxi FAIL formats: can't open input file `marquee.Aif': Unsupported AIFC compression type `SQS2'