An open API service indexing awesome lists of open source software.

https://github.com/ikskuh/livedecode

A super hacky tool to decode unknown binary formats
https://github.com/ikskuh/livedecode

Last synced: 3 months ago
JSON representation

A super hacky tool to decode unknown binary formats

Awesome Lists containing this project

README

          

# livedecode

Decode binary data on the fly quicker.

## Usage

```sh-session
[user@host project]$ livedecode example/png.spec example/example.png
```

The tool is meant to be run live while typing on a spec, so one can do stuff like this:
![screenshot of program usage](doc/screenshot.png)

Just run the program periodically in the background:

```sh-session
[user@host project]$ while true; do
clear
date
livedecode docs/wmb6.spec data/wmb/wmb6/block.wmb > /tmp/dump.txt
sleep 1
done
```

## Syntax

The format is a very crude line based syntax. Empty lines are ignored, everything past a `#` is a comment.
Lines are split into tokens separated by either space or tab characters.

The first token in a line determines the command or type of the line.
A line starting with `.` is a macro and is always executed. All other lines can be conditionally be executed.

If a line starts with a type, this type is decoded. If a name is given after the type, a variable is created with that name.

In a lot of places where not a name is expected, either immediate numbers can be written as decimal, hexadecimal (`0x1A`) or a variable reference can be used (`*variable`).

The parser can also accept tuple types, which are started by `(` and terminated by `)`. Tuples are inhomogenous arrays that are passed as a single argument. They are used for grouping arguments together.

Lines can be continued with a `\`, so the following code is considered a single line by the parser:

```
lut *key \
(key value) \
(key value) \
(key value) \
(key value) \
(key value)
```

## Commands, Macros and Variables

### Commands

#### `print …`

prints all arguments. if an argument is a semicolon, no space is printed after the argument. If a semicolon is last, no line feed is printed.

#### `def `

creates a variable called with the value . Useful for constants or aliases

#### `seek …`

sums up all offsets and moves the read cursor to the absolute position

#### `move …`

sums up all offsets and moves the read cursor relatively. Accepts negative numbers

#### `tell`

prints the file cursor

#### `tell

#### `dump `

dumps bytes

appends everything past the ! to the last created program

#### `call …`

invokes a program named . all arguments past that are passed as variables arg[0] to arg[n]

#### `array `

Creates an array of items called . In , the first occurance of `?` will be replaced with the array index. determines the type of the array items.

#### `array `

Creates an array of items called where is a sized type (str, blob, ...). In , the first occurance of `?` will be replaced with the array index. determines the type of the array items.

#### `select …`

Builds a variable name from and all provided s. For each key, the next `?` in the is replaced with the value of .
After all `?` are resolved, a global lookup is performed and the variable with the computed name is then copied into .

#### `endian le`

changes integer endianess to little endian

#### `endian little`

changes integer endianess to little endian

#### `endian be`

changes integer endianess to big endian

#### `endian big`

changes integer endianess to big endian

#### `bitread`

switches to bit-reading mode

#### `byteread`

switches out of bit-reading mode, discarding any unread bits in the current byte

#### `bitmap `

consumes a bitmap of size \* and rgb565, rgb888, bgr888, rgbx8888 or rgba8888

#### `bitmap

#### `lut ( ) …`

Will perform a lookup on value . If matches , the following is printed. Any number of pairs can be passed.

#### `divs

#### `diskdump bytes and writes them into a file called . Useful to extract portions of a file.

#### `findpattern …`

All arguments together form a pattern. This pattern is then searched in the file from the cursor position on and each occurrence is printed with offset.

Pattern components can either be a `*` for any kind of byte, or a list of `|`-separated integers that list the possibilities for this option.

To make this more clear, let's consider this example:
We're searching for a list of u32 that can only consist of the integer values 1, 2 or 3, but there's a unknown length marker at the start that is a 16 bit value less than 256:

```rb
# Search for at least 3 items:
# len item 0 item 1 item 2
findpattern * 0 1|2|3 0 0 0 1|2|3 0 0 0 1|2|3 0 0 0
```

### Macros

```rb
.if # the code following this will be executed if is not 0
.if # the code following this will be executed if is equals to
.else # swaps the current execution condition
.endif # ends a if block
.loop # Repeats the following code for times.
.loop # Repeats the following code for times. Writes the current index into .
.endloop # Terminates the current loop
.pgm # creates a new program called
.endpgm # ends the current program
```

### Types

```rb
u8 # 8 bit unsigned integer
u16 # 16 bit unsigned integer
u32 # 32 bit unsigned integer
u64 # 64 bit unsigned integer
i8 # 8 bit signed integer, two's complement
i16 # 16 bit signed integer, two's complement
i32 # 32 bit signed integer, two's complement
i64 # 64 bit signed integer, two's complement
f32 # 32 bit floating point
f64 # 64 bit floating point
str # ascii string of bytes, displayed as string+escapes
blob # binary blob of bytes, displayed as array
bitblob # binary blob of bits, displayed as array of bits (only valid in bit-reading mode)
bits # an unsigned integer of bits up to 64 (only valid in bit-reading mode)
```

### Predefined variables

```sh
str > file.path # The full path of the current file
str > file.name # The file name of the current file
u64 file.size # Size of the current file in bytes
```

## Example

```
endian le
u32 magic
u32 type
u32 offset
u32 length

print section 1
seek *offset
dump *length

.if *type 10
seek 0x200
str 10 description
.endif
```

A more complete example can be found [here](example/), which will decode a good amount of a PNG file.

## Building

1. Fetch the latest zig install (tested with `0.10.0-dev.4442+ce3ffa5e1`).
2. Invoke `zig build`.
3. Install `zig-out/bin/livedecode` into your system in a way you like it.