/truth

a multipass compiler for Touhou modding

Primary LanguageRustApache License 2.0Apache-2.0

truth

Build Status

Multipass compiler/decompiler suite for touhou binary script files.

Sexy error message example

truth stands for "touhou rust thing". Or maybe it stands for "touhou rust thtk". I dunno, I mostly just picked it because trustd and truecl sound pretty dope.

Tools provided:

  • trustd for .std files
  • truanm for .anm files
  • trumsg for most msg files
  • trumsg --mission for mission.msg

Supports all danmaku titles TH06–TH185. That is:

TH06 (EoSD), TH07 (PCB), TH08 (IN), TH09 (PoFV), TH09.5 (StB), TH10 (MoF), TH11 (SA), TH12 (UFO), TH12.3 (GFW), TH12.5 (DS), TH13 (TD), TH14 (DDC), TH14.3 (ISC), TH15 (LoLK), TH16 (HSiFS), TH16.5 (VD), TH17 (WBaWC), TH18 (UM), TH18.5 (BM)

Uwabami Breakers is also supported (use -g alcostg or -g 103)

Downloading

Get the latest Windows releases right here on GitHub!

Development builds may also be posted occationally on the #tools-dev channel on the ZUNcode discord server.

For even more bleeding edge, see Building from source below.

Docs

See these doc pages:

Using

STD files — trustd, and some general notes for all tools

Usage of trustd is pretty straightforward, so we'll take this opportunity to describe some features common to all of the tools.

Here's how you primarily use it:

trustd decompile -g13 -m map/any.stdm in.std -o out.stdspec

trustd compile -g13 in.stdspec -o out.std

The subcommands can be abbreviated to any unambiguous prefix, e.g. trustd decomp or even trustd d.

Similar to thtk, the -m flag imports an ECLMAP-style file. Generally speaking this is only needed during decompilation, because when you are compiling a script, it can contain a reference to its own mapfile:

#pragma mapfile "./map/any.anmm"

If you frequently decompile files for experimental purposes, you can also set the environment variable TRUTH_MAP_PATH to automatically locate mapfiles during decompilation. Each directory listed in this PATH-like variable will be checked for a file named any.stdm if you are compiling STD, any.anmm if you are compiling ANM, and etc.

ANM files — truanm

You can decompile an ANM file into a script, similar to thanm -l.

truanm decompile -g12 -m map/any.anmm in.anm -o out.spec

ANM files also contain images. You can extract these using truanm extract:

truanm extract -g12 in.anm -o images/

# shorthand
truanm x -g12 in.anm -o images/

At this time, image extraction is not thoroughly tested and may have some bugs.

Compilation and image sources

ANM scripts contain entry blocks that each declare an image contained in the ANM file.

// there are other fields, but most will use reasonable defaults
entry {
    path: "subdir/image.png",
    scripts: {
        sprite0: {id: 0, x: 0.0, y: 0.0, w: 50.0, h: 50.0},
    },
}

To compile an ANM file, you will likely need to supply some source of these images. There are two types of image sources: ANM files and image directories.

Recompiling existing ANM files

If you are recompiling a script obtained from an ANM file, the original ANM file will serve as a suitable image source, which can be provided through the -i/--image-source flag:

truanm compile -g12 edited.spec -i original.anm -o out.anm

When using an ANM file as an image source, each entry in the current script will pull the image from the entry with the same filepath inside the image source. This mechanism can also be used to copy over any missing metadata from an entry. In cases where multiple entries have the same path (which can happen for virtual files like "@" and "@R"), the duplicates are matched in order of appearance.

Creating brand new ANM files

If you have a thcrap patch or a directory containing the output of truanm extract, that can also be used as an image source:

truanm compile -g12 cool.spec -i path/to/images -o out.anm

In this case, the example entry above (with the path "subdir/image.png") would try to load path/to/images/subdir/image.png if it exists. As long as an image can be found, all fields on an entry will be automatically filled with reasonable defaults.

Mix and match

You can supply multiple image sources! For instance, if you are recompiling an ANM file and adding additional images (or replacing some of the images), you could supply:

truanm compile -g12 edited.spec -i original.anm -i my/extra/images -o out.anm

The ordering of the image sources is important when replacing images; here, -i my/extra/images appears last, so it takes top priority when multiple image sources define the same image.

Note that, similar to mapfiles, image sources can alternatively be defined inside the script using #pragma image_source:

// equivalent to prepending '-i original.anm -i my/extra/images' to argument list
#pragma image_source "original.anm"
#pragma image_source "my/extra/images"
Supplying dummy data

If you're using thcrap and something bothers you about the fact that both your ANM file and your thcrap patch contain copies of the same images, you can put has_data: "dummy" on an entry (the default is has_data: true). This will cause it to generate magenta dummy data in the ANM file, to be hot-swapped out by thcrap. Note that such an entry can still automatically grab the image dimensions from an image source.

MSG files — trumsg

MSG files are nothing special; just follow the same instructions for STD files, but using trumsg.

Well. Some MSG files are special:

  • mission.msg in TH095 and TH125 is a completely different format from other MSG files. To work with it you must supply the --mission flag.
  • Ending (e.g. e01.msg) and Staff Roll (e.g. staff1.msg) files use a different instruction set. It is possible to work with them but you'll need to create a special mapfile. Ping me on Discord and I'll see if I can throw one together.

Building and installing from source

Install rust, and then:

git clone https://github.com/ExpHP/truth
cd truth

# Debug builds  (for optimized builds, change it to `cargo run --release`)
cargo run -- trustd d -g10 -m map/any.stdm in.std -o out.stdspec
cargo run -- trustd c -g10 out.stdspec -o out.std

# If you want optimized binaries installed globally:
cargo install --path=.

Important: Notice that development builds use cargo run -- trustd instead of cargo run --bin=trustd. This is because most binaries in this project are actually shims around the main binary (truth-core), and if you do --bin=trustd then that main binary won't be rebuilt.