Skip to content

v0.5.0

Compare
Choose a tag to compare
@ExpHP ExpHP released this 15 May 00:06
· 67 commits to main since this release

Version 0.5.0 is a major release of the compiler containing many of the language additions that were found useful in alpha implementations of truecl. While truecl is still not officially released, these additions and improvements are available in all languages.

Added

Commands

  • Multiple -m args can now be provided.
  • Decompile commands now support -o/--output, just like compilation. This is extremely useful on Windows where redirection on STDOUT may produce a file in a different encoding from UTF-8 depending on the system configuration.
  • truanm had some unhelpful behavior when using multiple image sources that provide the same image, or when using has_data: "dummy" together with an image source. Image sources have been redesigned to better support common use cases.

Language features

  • INF, NAN, PI constants.
  • break keyword. This exits the nearest surrounding loop.
  • New type-cast syntax. The old _S and _f functions have been split into two types of operations: int(expr) and float(expr) for type-casts, and $(expr) and %(expr) to read a temporary as some type. (the two are the same in most languages, except EoSD ECL which does not auto-cast)
  • offsetof(label) and timeof(label) expressions. You can use these if you want to write a jump using ins_ syntax or the instruction alias. (these were a necessary addition for decompilation of EoSD ECL files that use conditional jumps in a funny way).
  • User-defined enums. A mapfile can define an enum:
    !enum(name="TestEnum")
    20 Red
    40 Blue
    
    which defines constants TestEnum.Red and TestEnum.Blue. An instruction can then specify that it takes an argument of this type, via a modified S argument:
    !ins_signatures
    100 S(enum="TestEnum")
    
    In this example, when calling ins_100 you will be able to use ins_100(Red) as a shorthand for ins_100(TestEnum.Red), and during decompilation it will try to decompile the values from this enum. Enums are open, in that the same enum can be defined multiple times or even across multiple mapfiles, and the list of consts will be merged.
  • Built-in enums:
    • bool. true and false are no longer keywords but rather members of a builtin enum bool. Use it like any other enum.
    • BitmapColorFormat. This now houses the constants FORMAT_ARGB_8888, FORMAT_RGB_565, FORMAT_ARGB_4444, and FORMAT_GRAY_8 used by img_format and rt_format in ANM files.
    • AnmSprite, AnmScript, MsgScript, EclSub. These get automatically generated from the names defined in a source script, allowing you to write e.g. S(enum="AnmSprite") and S(enum="AnmScript") instead of n and N. This makes them more flexible, allowing these types to be used in word-sized arguments and, in the future, timeline arg0.
  • Intrinsic mappings. (!ins_intrinsics) For instance, a patch which adds jump intrinsics to MSG could also provide a mapfile which tells trumsg about this intrinsic:
    !msgmap
    !ins_instrinsics
    100 Jmp()
    !ins_signatures
    100 ot
    
    and then you would be able to write loop { }s in MSG!

Improvements to decompilation

  • Can now detect of if/elseif chains that have no else block.
  • Many improvements to detection of nested if/elses and loops.
  • Decompiling intrinsics will fall back to instruction syntax if the intrinsic cannot be decompiled. (e.g. PCB stage 7 ECL has a set_int instruction that tries to assign to an immediate)
  • Decompiling sub/script/sprite names will fall back to raw integers if the corresponding items don't exist.

Compatibility notes

  • Using registers (e.g. $REG[8]) in a format without registers such as STD is now detected as an error.
  • If e.g. X is an alias for $REG[3], then using both X and REG[3] in the same function body will now generate a warning. Similarly, using two different aliases (e.g. X and Y) for the same register will also warn.
    • This is partly so that, in future versions of truth that provide truecl, the compiler can call attention to accidental usage of EoSD's I0 or PCB's "param" registers in subs where these registers are already implicitly in use by function parameters.
  • Previously, using -m mapfile.eclm during decompilation would disable lookup from TRUTH_MAP_PATH. Now that multiple -m are supported, this behavior now seems surprising, so TRUTH_MAP_PATH is now always searched during decompilation.

Internal changes

  • The order and encoding of arguments to intrinsics is no longer hardcoded by game/format, but rather inferred from the mapfile signature, meaning it can be defined by the user. So for instance, a CondJmp(op="=="; type="float") could have any of the signatures otff, toff, ffto, or ffot, and these would all be encoded correctly by the compiler.
  • Time labels are now internally stored as statements. This drastically simplifies parsing and some aspects of loop compilation/decompilation.