-
Notifications
You must be signed in to change notification settings - Fork 69
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #732 from Daft-Freak/patch-3
Start documenting the firmware/launcher/PIC magic
- Loading branch information
Showing
1 changed file
with
103 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,103 @@ | ||
# 32blit STM32 Firmware Internals <!-- omit in toc --> | ||
|
||
- [PIC](#pic) | ||
- [.blit File Format](#blit-file-format) | ||
- [Relocation header](#relocation-header) | ||
- [The Executable](#the-executable) | ||
- [Game Metadata](#game-metadata) | ||
- [The Firmware](#the-firmware) | ||
- [The Launcher](#the-launcher) | ||
|
||
## PIC | ||
|
||
To allow multiple games to be "installed" in the 32MB flash memory at the same time, all games are built as position-independent code with these flags: `-fPIC -mno-pic-data-is-text-relative -mno-single-pic-base`. A relocation header is appended and the firmware relocates games while writing to flash. | ||
|
||
This also requires custom builds of newlib/libstdc++ with the same flags, which are [provided here](https://github.com/32blit/stdlibs/). | ||
|
||
## .blit File Format | ||
The `.blit` format has three parts, there's a relocation header, the executable and the game metadata. | ||
|
||
### Relocation header | ||
|
||
The relocation header is a list of offsets in the executable that get an offset added to them as the game is written to flash (through the serial port or using the launcher to "run" from SD). | ||
|
||
For example, if a game is written to the second "block" of flash, `0x10000` will be added to each listed offset in the binary. | ||
|
||
The format of this header is: | ||
|
||
```c | ||
{ | ||
uint32_t magic; // "RELO" | ||
uint32_t num_relocs; // Number of relocation entries | ||
uint32_t relocs[]; // the addresses to relocate | ||
} | ||
``` | ||
|
||
This header is generated by the [`relocs` tool](https://github.com/32blit/32blit-tools/blob/master/src/ttblit/tool/relocs.py) in 32blit-tools and is not written to flash when a game is installed. | ||
|
||
### The Executable | ||
|
||
The raw game binary generated with `arm-none-eabi-objcopy -O binary ...`. It has a small header created by the linker: | ||
|
||
|
||
```c | ||
struct BlitGameHeader { | ||
uint32_t magic; // "BLIT" | ||
|
||
BlitRenderFunction render; // pointer to the render function | ||
BlitTickFunction tick; // pointer to blit::tick, which calls update and updates timers/tweens | ||
BlitInitFunction init; // pointer to the init function | ||
|
||
uint32_t end; // the address of the end of the game binary (0x90000000 + the size of the binary) | ||
uint32_t start; // the address of the start of the game (always 0x90000000, not used) | ||
}; | ||
``` | ||
|
||
The end address is used to locate the metadata. | ||
|
||
### Game Metadata | ||
|
||
The metadata is appended to the end and has the info generated by the [`metadata` tool](https://github.com/32blit/32blit-tools/blob/master/src/ttblit/tool/metadata.py) from the `metadata.yml` file. | ||
|
||
There are multiple parts to this as the format has been extended. | ||
|
||
```c | ||
struct RawMetadata { | ||
char[8] magic; // "BLITMETA" | ||
uint16_t size; // size of entire metadata | ||
|
||
uint32_t crc32; // these two are generated by the tools | ||
char datetime[16]; // | ||
char title[25]; | ||
char description[129]; | ||
char version[17]; | ||
char author[17]; | ||
}; | ||
|
||
// Prefixed with "BLITTYPE". Extended metadata - older .blits may not have this | ||
struct RawTypeMetadata { | ||
char category[17]; // the "launcher" category has special meaning | ||
char url[129]; // can be anything, but points to the GitHub repo most of the time | ||
uint8_t num_filetypes; // used for launcher file associations | ||
char filetypes[][5]; // | ||
}; | ||
|
||
``` | ||
|
||
Two packed images usually follow these for the icon/splash. This is the same format as generated for images by the asset packer and starts with either "SPRITERW", "SPRITEPK" or "SPRITERL". | ||
|
||
|
||
## The Firmware | ||
|
||
The firmware is installed to the "internal" handles all the hardware stuff, including flashing games and switching between them. It also handles the system menu. | ||
|
||
At startup, the firmware scans through "external" flash to find installed games and builds a list of "games" with file associations. This can be used for interpreters (like 32blit-lua), or emulators (DaftBoy32). | ||
|
||
The interface between the games/firmware is in [`32blit/engine/api_private.hpp`](https://github.com/32blit/32blit-sdk/blob/master/32blit/engine/api_private.hpp). | ||
|
||
|
||
## The Launcher | ||
|
||
The launcher is actually mostly a regular game, with a category of "launcher". The firmware switches to this whenever a game is not running. | ||
|
||
It uses some "semi-private" firmware API to handle launching/flashing games. It's possible to replace the launcher entirely, like [this extremely basic one](https://github.com/Daft-Freak/32blit-misc/tree/main/launcher-test). |