The framework is still under development
The documentation in this section refers to the Game Bub Core Framework
as of v1.1-beta. The framework is not finalized, and may change
based on developer feedback.
Reference: Metadata¶
When reading a core from the microSD card at /cores/<core id>, the host MCU reads core metadata from the following JSON files:
core.json: Info, bitstreams, and hardware requirements (Required)files.json: Files to read/write/persist between the microSD card and the core (Optional)settings.json: User-configurable core settings and actions (Optional)
core.json¶
Contains top-level information about the core and a list of FPGA bitstream files.
| Field | Type | Default | Description |
|---|---|---|---|
metadata |
Object | Required | Core information |
metadata.id |
String | Required | Unique core identifier (e.g. "Demo.DemoCore"), max 32 chars |
metadata.name |
String | Required | Human-readable core name, max 32 chars |
metadata.author |
String | Required | Human-readable core author, max 32 chars |
metadata.version |
String | null |
Human-readable version code, max 16 chars |
metadata.release_date |
String | null |
Release date, "YYYY-MM-DD" |
metadata.url |
String | null |
URL to website with information, max 64 chars |
metadata.license |
String | null |
SPDX license identifier, max 32 chars |
bitstreams |
Array | Required | List of bitstream paths / targets |
bitstreams[].target |
String | Required | Target hardware for the bitstream (e.g. gamebub_rev4) |
bitstreams[].filename |
String | Required | Filename of the bitstream, max 32 chars, ends with .bit |
hardware |
Object | {} |
Hardware flags |
hardware.cartridge_enable |
String | "no" |
Whether the cartridge slot should be enabled ("no", "yes", "if_selected") |
hardware.cartridge_selectable |
Boolean | false |
Whether the user can select "Run Cartridge" |
Example¶
{
"metadata": {
"id": "Demo.DemoCore",
"name": "Demo Core",
"author": "Demo",
"version": "1.0.0",
"license": "CERN-OHL-W-2.0",
},
"bitstreams": [
{ "target": "gamebub_rev4", "filename": "DemoCore-rev4.bit" },
{ "target": "gamebub_rev2", "filename": "DemoCore-rev2.bit" }
]
}
files.json¶
Optional. Defines data files (e.g. ROMs, save files, assets) that need to be loaded into and/or saved out of the core.
A maximum of 8 files may be defined.
| Field | Type | Default | Description |
|---|---|---|---|
files |
Array | Required | List of files, max 8 entries |
files[].id |
Integer | Required | File ID (0 to 65535) |
files[].label |
String | Required | Human-readable file label, max 16 chars |
files[].filename |
String | null |
Optional fixed path relative to the core directory, max 32 chars |
files[].extensions |
Array | [] |
File extensions for the file, max 4 items, max 8 chars each |
files[].optional |
Boolean | true |
Whether the core will run if the file is missing |
files[].read_only |
Boolean | false |
If true, changes will not be saved back to the microSD card |
files[].user_selected |
Boolean | false |
Whether the user is prompted to choose the file |
files[].dependent_on_0 |
Boolean | false |
Whether the path is derived from File 0 (see below) |
files[].initialize |
Boolean | false |
If true and the file is missing, memory is initialized with 0xFF |
files[].address |
Hex | Required | Memory-mapped target base address in core memory |
files[].max_size |
Hex | 0 |
Maximum allowed file size in bytes (0 = no limit) |
files[].exact_size |
Hex | 0 |
Exact required file size in bytes (0 = no check) |
files[].max_transfer_speed |
Integer | 5000 |
Maximum transfer rate in KB/s |
Any field marked as "Hex" is either a JSON number or a hexadecimal string, e.g. "0x0000ABCD" or 43981.
If a file has ID 0, it is treated specially. If "Run Cartridge" is selected, neither File 0 nor any file dependent on File 0 will be loaded.
If a file is dependent on File 0 (and File 0 is loaded), it will derive its path from File 0, with the first (and only) extension in extensions used as its file extension. For example, if File 0 resolves to /some-path/data.bin, and its extensions is ["sav"], the File will be loaded from the path /some-path/data.sav.
If a file is given a filename, it will be loaded from that filename relative to the core directory. E.g. with a filename of asset.bin, it could be loaded from /cores/Demo.DemoCore/asset.bin.
During core setup, for each file selected (or 0xFF-initialized):
FileWriteStartcommand- The file is written to
addressacross the Host memory interface FileWriteEndcommand
Similarly, during core exit, for each file that was loaded (except read_only files):
FileReadStartcommand- The file is read from
addressacross the Host memory interface FileReadEndcommand
Example¶
{
"files": [
{
"id": 0,
"label": "ROM",
"extensions": ["bin"],
"user_selected": true,
"optional": false,
"read_only": true,
"address": "0x30000000",
"max_size": "0x800000"
},
{
"id": 1,
"label": "Save",
"extensions": ["sav"],
"user_selected": false,
"dependent_on_0": true,
"optional": true,
"initialize": true,
"address": "0x40000000",
"max_size": "0x10000"
},
{
"id": 2,
"label": "BIOS",
"filename": "bios.bin",
"optional": false,
"read_only": true,
"address": "0x10000000",
"exact_size": "0x100"
}
]
}
settings.json¶
Optional. Defines user-configurable settings, set by the user in the in-core menu. A maximum of 16 settings may be defined.
Settings are written to the core (via the host memory interface) both during setup and whenever the user changes them. Settings are persisted when the core exits.
| Field | Type | Default | Description |
|---|---|---|---|
settings |
Array | Required | List of settings, max 16 entries |
settings[].id |
Integer | Required | Setting ID (0 to 65535) |
settings[].label |
String | Required | Human-readable setting name |
settings[].address |
Hex | Required | Memory address (in core) to write setting value |
settings[].mask |
Hex | 0 |
Mask applied when modifying setting |
settings[].default |
Hex | 0 |
Default value for the setting |
settings[].type |
String | Required | Type of setting (see below) |
Any field marked as "Hex" is either a JSON number or a hexadecimal string, e.g. "0x0000ABCD" or 43981.
When a setting is written to the core, it is written as a single 32-bit access over the host memory interface. If mask is not 0, the address is first read, then ANDed with the mask, and then ORed with the new value. This allows multiple settings to be crammed into the same 32-bit register.
Setting Types¶
"list"
A list of choices, each with a label and associated value:
| Field | Type | Default | Description |
|---|---|---|---|
settings[].items |
Array | Required | List of selection choices, max 8 items (required when type is "list") |
settings[].items[].label |
String | Required | Human-readable label for this list option |
settings[].items[].value |
Hex | Required | Value written to address when this option is selected |
"action"
A button, which writes value every time it is selected. Not exactly a setting.
| Field | Type | Default | Description |
|---|---|---|---|
settings[].value |
Hex | Required | Value written when activated |
"checkbox"
A yes/no checkbox. When checked, writes value. When not checked, writes 0.
| Field | Type | Default | Description |
|---|---|---|---|
settings[].value |
Hex | Required | Value written when checked |
Example¶
{
"settings": [
{
"id": 0,
"label": "Reset Core",
"address": "0x004",
"type": "action",
"value": "0x1"
},
{
"id": 1,
"label": "Slow Mode",
"address": "0x008",
"default": "0x0",
"type": "checkbox",
"value": "0x1"
},
{
"id": 2,
"label": "Paddle Color",
"address": "0x100",
"default": "0xFFFFFF",
"type": "list",
"items": [
{ "label": "White", "value": "0xFFFFFF" },
{ "label": "Red", "value": "0xFF0000" },
{ "label": "Green", "value": "0x00FF00" }
]
}
]
}