Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Document pdex.bin file format and improve conversion script #24

Merged
merged 3 commits into from
Jul 15, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
53 changes: 53 additions & 0 deletions formats/pdex.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
The `pdex.bin` file represents information and executable code copied by `pdc` from a `pdex.elf` ELF file compiled for ARM32 (Thumb, EABI v5, hard-float). It is usually the entry point of Playdate games created using the C API. The file format uses little endian byte order.

Supplementary reading:

- https://en.wikipedia.org/wiki/Executable_and_Linkable_Format
- https://www.man7.org/linux/man-pages/man5/elf.5.html

# File structure

1. [File header](#file-header)
2. [Program header](#program-header)
3. [Program data](#program-data)
1. [Program segment](#program-segment)
2. [Relocation entries](#relocation-entries)

## File header

| Offset | Type | Detail |
|:-------|:-----------|:-------------------------------|
| `0x00` | `char[12]` | File signature: `Playdate PDX` |
| `0x0C` | `uint32` | [Flags](#flags) |
| `0x10` | - | End of file header (size) |

### Flags

| Bitmask | Detail |
|:--------------------|:------------------------------------------------------|
| `flag & 0x40000000` | If `> 0`, all data after the file header is encrypted |

Encryption is (at the time of writing) only used by Catalog games as a form of DRM. The encryption method is not yet known.

## Program header

| Offset | Type | Detail |
|:-------|:------------|:---------------------------------------------------|
| `0x00` | `uint8[16]` | MD5 checksum of program segment |
| `0x10` | `uint32` | Size of program segment in file image; `p_filesz` |
| `0x14` | `uint32` | Size of program segment in memory image; `p_memsz` |
| `0x18` | `uint32` | Entry point address; `e_entry` |
| `0x1C` | `uint32` | Number of relocation entries |
| `0x20` | - | End of program header (size) |

## Program data

The program data is zlib-compressed and consists of [a single program segment](#program-segment) immediately followed by [relocation entries](#relocation-entries).

### Program segment

The first `p_filesz` bytes of the uncompressed program data is the program segment, usually consisting of the `.text` (executable code) and `.data` (initialized global variables) sections of the original ELF file. The `.bss` (uninitialized global variables) section does not occupy any space in the file image; its size in memory can be computed via `p_memsz - p_filesz`.

### Relocation entries

The next `<number of relocation entries> * 4` bytes of the uncompressed program data are the relocation entries, usually from the `.rel.text` and/or `.rel.data` sections of the original ELF file. Each entry is a single `uint32` denoting a byte offset from the beginning of the program segment where a relocation should take place, corresponding to the `r_offset` member of an `Elf32_Rel` relocation entry.
5 changes: 3 additions & 2 deletions readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ Unofficial Playdate reverse-engineering notes/tools - covers file formats, serve

- **File Formats**
- **Playdate game formats**
- [**pdex.bin**](formats/pdex.md) - Executable code
- [**.luac**](formats/luac.md) - Lua bytecode
- [**.pdz**](formats/pdz.md) - File container
- [**.pda**](formats/pda.md) - Audio file
Expand All @@ -25,8 +26,8 @@ Unofficial Playdate reverse-engineering notes/tools - covers file formats, serve

## Tools

- [**`pdz.py`**](tools/pdz.py) - Unpacks all files from a `.pdz` file container
- [**`pdex2elf.py`**](tools/pdex2elf.py) - Converts a `pdex.bin` to an ELF file that can be analysed in a decompilation tool such as Ghidra
- [**`pdz.py`**](tools/pdz.py) - Unpacks all files from a `.pdz` file container.
- [**`pdex2elf.py`**](tools/pdex2elf.py) - Converts a `pdex.bin` to an ELF file that can be analyzed in tools such as readelf, objdump or Ghidra, or compiled back to the same original `pdex.bin` by `pdc`.
- [**`usbeval.py`**](tools/usbeval.py) - Uses the Playdate's USB `eval` command to evaluate a Lua script over USB. Has access to the Lua runtime of the currently loaded game, except for system apps.

## Related Projects and Resources
Expand Down
Loading