Files
GameAndWatch_MiSTer/docs/format.md
2026-05-18 14:41:01 -05:00

5.4 KiB

Format

The MAME ROM format is not conducive to FPGA use, so we have to package up all of the assets into a new format. This format is designed with space for growth, but it should cover most usecases (i.e. games) already.

First is a config section of 0x100 bytes, followed by two byte interleaved 720x720 images, 0x2DB40 bytes of mask config, and finally the ROM data.

Config

First bit is version. Spec V1 is as follows:

0x0: [version 8 bits (01)][mpu 8 bits][screen configuration 8 bits][screen width|screen height 24 bits][reserved 16 bits]
0x8: input mapping 40 bytes - [s0 config 4 bytes][s1 config 4 bytes] ... [s7 config 4 bytes][b config 1 byte][ba config 1 byte][acl config 1 byte][grounded port index 1 byte][reserved 4 bytes]
0x30: Start of reserved space - This is reserved for future functionality
0x79: [generator tool commit (ascii) 7 bytes]
0x100: Start of byte interleaved images
0x2F7700: [mask config 0x2DB40 bytes] End of images, start of mask config
0x325240: ROM data
0x326240: [SM511/SM512/SM530 melody ROM 0x100 bytes, when present]

0000_1101_11 -> 00_0011_0111

MPU

MPU Conf. Value
SM510 0x0
SM511 0x1
SM512 0x2
SM530 0x3
SM5a 0x4
SM510 + Tiger 0x5
SM511 + Tiger 1 bit 0x6
SM511 + Tiger 2 bit 0x7
KB1013VK12 0x8

Screen Configuration

Screen Config Conf. Value
Single screen 0x0
Dual Vertical 0x1
Dual Horizontal 0x2
Triple Horizontal 0x3

12 bits each for screen width/height. For triple-horizontal packages, the legacy size field stores the middle screen size; the renderer uses the actual per-screen SVG bounds.

Input Mapping

Each button can be ~32 items. For alignment, assign a full 8 bits to each. There can be a maximum of 8 S ports (of 4 values), and 1 for B, BA, and ACL (in that order). We also add a "grounded input port index", which indicates which index of S port, if any, is grounded and thus is always active, ORed with the other input bits. Thus there are 8 * 4 + 4 = 36 bytes required for full config.

Each entry byte takes the form:

[active low 1 bit][reserved 2 bits][input 5 bits]

The unused/unset controller byte is assigned 0x7F for clarity.

NOTE: These won't all be addressable given a normal input scheme, given the limited number of buttons on controllers.

The grounded input port is 0 when unset, and the 1-based index otherwise (so "groundLastIndex": 0 implies a format value of 1).

Input Name Config Value
JoyUp 0
JoyDown 1
JoyLeft 2
JoyRight 3
Button1 4
Button2 5
Button3 6
Button4 7
Button5 8
Button6 9
Button7 10
Button8 11
Select (typically Time) 12
Start1 (Game A) 13
Start2 (Game B) 14
Service1 15
Service2 16
LeftJoyUp 17
LeftJoyDown 18
LeftJoyLeft 19
LeftJoyRight 20
RightJoyUp 21
RightJoyDown 22
RightJoyLeft 23
RightJoyRight 24
VolumeDown 25
PowerOn 26
PowerOff 27
Keypad 28
Custom 29
CustomUpDown 30
CustomButtonHour 31
Mark Unused 0x7F

Images

Images are byte interleaved values of background and mask images. The background is the first byte, and is the lowest byte in each word.

Mask

The mask data correlates the mask pixel data with the LCD segment as defined in the MAME file. The 10 bit id provides the x, y, and z coordinate values for each segment, which allows the CPU to address them via the S shifter or W shift registers.

The x, y coordinates of the start of a run of mask pixels is recorded, along with the length of the run. Thus we can minimize the number of bytes required for a contiguous strip of pixels.

40 bits: [id 10 bits][x 10 bits][y 10 bits][length 10 bits]...next
id: [row/z 2 bits][column/y 4 bits][line/x 4 bits]
0x2DB40 bytes total - 720 rows, average of 52 entries, 5 bytes each

ROM Data

The CPU program ROM starts at 0x325240. SM510 and SM5a packages keep their existing behavior and end after the program ROM data.

SM511/SM512/SM530 packages pad the program ROM area to 0x1000 bytes and append the 256 byte melody ROM at 0x326240. This keeps the old package layout compatible while giving the core a fixed melody ROM load address.