Skip to content

Transform Specification

RetroFloppySupport edited this page Dec 28, 2019 · 4 revisions

The instructions for making the various transformations you want are simply listed in a plain text file. A transform file might look like this, for example:

; Change 0x00 to 0x20
00 = 20

The left side of the equals sign, hash mark, or percent sign is the byte pattern to search for in undecorated hexadecimal notation. To specify it, the following conventions are used:

  • A byte pattern, given in even numbers of hex digits, with no other decoration; i.e. 0d0a32ea4f
  • A byte pattern combined with "don't care" values consisting of even numbers of non-hex digits (periods/full stops are preferred but not enforced); i.e. 0d0a....4f
  • A byte pattern combined with "must not be zero" values consisting of even numbers of exclamation points; i.e. 0d0a32!!4f

The right side can be blank, another byte pattern given in undecorated hex, or ASCII text if surrounded in double quotes. Some examples:

; Hard newline
8d = 0d0a

; 0x86 appeared at the beginning of files sometimes, after the preamble.  Remove it.
86 =

; Start of heading
83 = "\par\par\pard\s2\b\fs36 "

; Italics on - RTF
b12d31 = "\i "

; Italics off - RTF
b12d30 = "\i0 "

There is a special case for specifying returns and newlines. If you need to translate a byte pattern into something that includes them, you need to escape the backslash. For example:

; Newline production
7a0a1531 = "\\r\\n"

Specification Elements

Comment: ;

Any line starting with a semicolon will not be considered. Adding a semicolon mid-line will have generally undefined results. Example:

; This text will not be considered

Replacement: =

Replace the left side of the equals with what's on the right side and move past the replacement looking for the next match. Example:

; Replace nulls with spaces
00 = 20

Replace with Repeat: #

Replace the left side of the hash with what's on the right side and re-consider the just-replaced data for more matches. Example:

; Add a newline - may need to add two
8d # 0d0a
0d0a9d = 0d0a0d0a

Replace with Toggle: %

Replace the left side of the percent with what's on the right side, alternating between two values separated by commas. Example:

; Toggle italics on and off
7f047f % "\i1 ","\i0 "

Shift Byte Range: [xx..yy] = zz

Shift a byte range byte-for-byte to a different range starting at the value after the equals sign, or remove them altogether. Examples:

; Shift 0x41 through 0x5a up to 0x61
[41..5a] = 61

; Remove 0xf0 through 0xff
[f0..ff] = 

End of File Calculation: eof_lo,eof_mid,eof_hi,eof_offset

Used together when a file contains a binary length of file vector. eof_lo is the least significant byte, eof_mid is the next most signficant byte, and eof_high is the most significant byte of the vector. These values together comprise lookups of an offset to calculate the end of the file. eof_offset is a static offset to tune the exact end point in case the vector is offset by some amount. This calculated EOF value will be used to stop considering text after it is reached. Example:

; Calculate the EOF based on file contents
; length vector is 0x7c into the file, actual EOF is 0x100 bytes later than calculated
eof_hi = 00
eof_mid = 7d
eof_lo = 7c
eof_offset = 100

Header Definition: head

Specifies a prefix to add to the beginning of the resultant file. Example:

; Header for HTML format
head = "<html>"

Trailer Definition: tail

Specifies a suffix to add to the end of the resultant file. Example:

; Trailer for HTML format
tail = "</html>"

Trim Leading Bytes: trim_leading

Specifies a number of bytes to trim off the beginning of the input file (counted in hex bytes) before any binary transforms are applied. Example:

; Trim the leading 0x400 bytes
trim_leading = 0400

Trim Trailing Bytes: trim_trailing

Specifies a number of bytes to trim off the end of the input file (counted in hex bytes) before any binary transforms are applied. Results are undefined if used in conjunction with eof_* vectors. Example:

; Trim the trailing 0xDF bytes
trim_trailing = df

Remove between two delimiters: remove_between

Remove everything between two delimiters specified in hex bytes (including the delimiters themselves). Once a beginning delimiter is found, everything is consumed until the end delimiter is found - including additional beginning delimiters, so nesting is not supported. Example:

; Remove everything between ABC and DEF
remove_between = 414243,444546

Regular Expression Replacement: regex

Specifies a textual regular expression to run on the output after any and all binary transforms are applied; multiple regex expressions are allowed, one per line; the first character in the string serves as the delimiter. Example:

; Remove margin specs: zlmxx, :rmxx
regex = @[z|:][l|r]m[0-9]*@@

Seek Start of File: {@@<FiLe_SoF>@@}

Special value signifying the value to seek that signifies the start of file; when the value specified on left side of the equals is first found, everything up to that point will be discarded. Example:

; SOF is \r\n
0d0a53 = "{@@<FiLe_SoF>@@}"

Seek Start of File - Multiple: {@@<FiLe_SoF_GrEeDy>@@}

Special value signifying the start of file; when the value specified on left side of the equals is found for the final time in a file, everything up to that point will be discarded. Example:

; SOF may appear several times; use the last one
1f = "{@@<FiLe_SoF_GrEeDy>@@}"

Seek End of File: {@@<FiLe_EoF>@@}

Special value signifying the end of file; everything found after that value will be discarded. Example:

; EOF is ctrl-Z
1a = "{@@<FiLe_EoF>@@}"

Example Transforms

The Transformenator project comes with many example transforms used to convert various early binary word processor formats to RTF, HTML, or plain ASCII text. Some transforms include the ability to extract individual files from disk images at the same time. You can see the list of available "internal" transforms by invoking the transformenator jar with no parameters, like so:

java -jar transformenator.jar

The source to these internal transforms is available in github at this link.