RGBGFX(1)

๐Ÿ“ฆ
version 1.0.4 ยท 4 versions
, in arch rolling, nixpkgs unstable

โœจ NAME โœจ

okay so this is the rgbgfx(1) page from the General Commands Manual ๐Ÿ’– โ€” meet rgbgfx, the Game Boy graphics converter ๐ŸŽฎโœจ. That's the whole name vibe: it converts graphics for the Game Boy, and it's about to be your bestie for tile data.


โœจ SYNOPSIS โœจ

rgbgfx [-CmhOuVwXYZ] [-v [-v ...]] [-a attrmap | -A] [-B color]
       [-b base_ids] [-c pal_spec] [--color when] [-d depth]
       [-i input_tiles] [-L slice] [-l base_pal] [-N nb_tiles]
       [-n nb_pals] [-o out_file] [-p pal_file | -P] [-q pal_map | -Q]
       [-r width] [-s nb_colors] [-t tilemap | -T] [-W warning]
       [-x quantity] file

๐Ÿ’– DESCRIPTION ๐Ÿ’–

The rgbgfx program converts PNG images into data suitable for display on the Game Boy and Game Boy Color, or vice-versa ๐Ÿ”ฅ. Yes, both directions, no cap.

Its main character function is to divide the input PNG into 8ร—8 pixel squares, convert each of those squares into 1bpp or 2bpp tile data, and save all of the tile data in a file ๐ŸŽ€. It also has options to generate a tile map, attribute map, and/or palette set as well; more on that and how the conversion process can be tweaked below ๐Ÿซถ.


๐Ÿซถ ARGUMENTS ๐Ÿซถ

okay so rgbgfx accepts the usual short and long options, such as -V and --version ๐Ÿ’…. Options later in the command line override those set earlier, except for when duplicate options are considered an error. (So order matters, bestie, and duplicates can be a whole thing ๐Ÿ˜ญ.)

Options can be abbreviated as long as the abbreviation is unambiguous: --verb is --verbose, but --ver is invalid because it could also be --version. iykyk โœจ.

Unless otherwise noted, passing - (a single dash) as a file name makes rgbgfx use standard input (for input files) or standard output (for output files) ๐ŸŒˆ. To suppress this behavior, and open a file in the current directory actually called -, pass ./- instead. Using standard input or output for more than one file in a single command may produce unexpected results. So like, don't juggle too many dashes at once ๐Ÿ™ˆ.

rgbgfx accepts decimal, hexadecimal, octal, and binary for numeric option arguments ๐Ÿ”ข. Decimal numbers are written as usual; hexadecimal numbers must be prefixed with either $ or 0x; octal numbers must be prefixed with either & or 0o; and binary numbers must be prefixed with either % or 0b. (The prefixes $ and & will likely need escaping or quoting to avoid being interpreted by the shell.) Leading zeros (after the base prefix, if any) are accepted, and letters are not case-sensitive. For example, all of these are equivalent: 42, 042, 0x2A, 0X2A, 0x2a, &52, 0o52, 0O052, 0b00101010, 0B101010. Numeric mood, iconic behavior ๐Ÿ’œ.

The following options are accepted:

  • -a attrmap, --attr-map attrmap โ€” generate an attribute map, which is a file containing tile โ€œattributesโ€ ๐Ÿ’…. For each square of the input image, its corresponding attribute map byte contains the mirroring bits (if -m was specified), the bank bit (see -N), and the palette index. See Pan Docs: https://gbdev.io/pandocs/Tile_Maps#bg-map-attributes-cgb-mode-only for the individual bytes' format. The output is written just like the tile map (see -t), follows the same order (-Z), and has the same size. Slay, but make it byte-level.
  • -A, --auto-attr-map โ€” same as -a base_path.attrmap (see โ€œAutomatic output pathsโ€). Auto mode, cute ๐ŸŽ€.
  • -B color, --background-color color โ€” set a background color to be omitted from output. Colors are accepted in #rgb or #rrggbb format, or as transparent. Input tiles which are entirely the specified background color are ignored and will not be output in tile data file. The tilemap, atrribute map, or palette map files will use placeholder values where background tiles were. If a background color is specified, it cannot be used within tiles which are not ignored. Lowkey important: that color is not allowed inside non-ignored tiles, periodt.
  • -b base_ids, --base-tiles base_ids โ€” set the base IDs for tile map output. base_ids should be one or two numbers between 0 and 255, separated by a comma; they are for bank 0 and bank 1 respectively. Both default to 0. Cute little ID assignment moment ๐Ÿ’–.
  • -C, --color-curve โ€” modifies the color palettes (whether they are generated from the input image or taken from an input palette specification) with a color curve mimicking the Game Boy Color's screen ๐ŸŒˆ. This adjusts the absolute RGB color values so that the perceived colors, when displayed on Game Boy Color hardware (or an emulator with an accurate display filter), will look like the original colors as displayed on a backlit computer screen. Note that GBC displays can look very different depending on the ambient light and their exact hardware model, so this color curve is only a "best effort". It's giving โ€œwe tried, bestieโ€ ๐Ÿ˜ญ.
  • -c pal_spec, --colors pal_spec โ€” use the specified color palettes instead of having rgbgfx automatically determine some. pal_spec can be one of the following:
    • inline palette spec โ€” if pal_spec begins with a hash character #, it is treated as an inline palette specification. It should contain a comma-separated list of hexadecimal colors, each beginning with a hash. Colors are accepted in #rgb or #rrggbb format. To leave one or more gaps in the palette, #none can be used instead of any color. Palettes must be separated by a colon or semicolon (the latter may require quoting to avoid special handling by the shell), and spaces are allowed around colons, semicolons and commas; trailing commas and semicolons are allowed. See โ€œEXAMPLESโ€ for an example of an inline palette specification. So valid, so slay ๐Ÿ’….
    • embedded palette spec โ€” if pal_spec is the case-insensitive word embedded, then the first four colors of the input PNG's embedded palette are used. It is an error if the PNG is not indexed, or if colors other than these 4 are used. (This is different from the default behavior of indexed PNGs, as then unused entries in the embedded palette are ignored, whereas they are not with -c embedded.) Four colors, no exceptions, got it? ๐ŸŽ€
    • DMG palette spec โ€” if pal_spec starts with case-insensitive dmg=, then the following two-digit hexadecimal number specifies four grayscale DMG color indexes. The number functions like the DMG's $FF47 BGP register (see Pan Docs: https://gbdev.io/pandocs/Palettes.html for more information): the low two bits 0-1 specify which gray shade goes in color index 0, the next two bits 2-3 specify which gray shade goes in color index 1, and so on. Gray shade 0 is the lightest (white), 3 is the darkest (black). If pal_spec is the case-insensitive word dmg, then it acts like dmg=E4, i.e. the darkest gray will end up in color index 0, and so on. The same gray shade cannot go in two color indexes. To specify a DMG palette, the input PNG must have all its colors in shades of gray, without any transparent colors. Vintage DMG palette moment ๐Ÿ•น๏ธ.
    • automatic palette generation โ€” if pal_spec is the case-insensitive word auto, then a palette is automatically generated using the procedure described in โ€œPALETTE GENERATIONโ€. This is the default behavior if -c was not specified. Auto mode is the main character when you don't pick anything โœจ.
    • external palette spec โ€” otherwise, pal_spec is assumed to be an external palette specification. The expected format is format:path, where path is a path to a file (- is not treated specially), which will be processed according to the format. See โ€œPALETTE SPECIFICATION FORMATSโ€ for a list of formats and their descriptions. External files, iconic ๐Ÿ“.
  • --color when โ€” specify when to highlight warning and error messages with color: always, never, or auto. auto determines whether to use colors based on the NO_COLOR: https://no-color.org/ or FORCE_COLOR: https://force-color.org/ environment variables, or whether the output is to a TTY. So yes, the whole env-var-or-TTY vibe check ๐ŸŒˆ.
  • -d depth, --depth depth โ€” set the bit depth of the output tile data, in bits per pixel (bpp), either 1 or 2 (the default). This changes how tile data is output, and the maximum number of colors per palette (2 and 4 respectively). Depth decisions, but make them bpp ๐Ÿ’….
  • -h, --help โ€” print help text for the program and exit. (Help text wraps to the value of the COLUMNS environment variable if that is defined as nonzero; or else to the console window width if output is to a TTY.) Helpful bestie behavior ๐Ÿซถ.
  • -i input_tiles, --input-tileset input_tiles โ€” use the specified input tiles in addition to having rgbgfx automatically determine some. The input tiles will always be first in the -o image output, and will always get the first IDs in the -t tilemap output. input_tiles must contain 1bpp or 2bpp tile data (whichever matches the -d option used here), as could be previously generated with the -o option.

If the -o option is also specified, then the input tiles will be assigned the first tile IDs, and any tiles from the input image that are not in the input tileset will be assigned subsequent IDs. But if the -o option is not specified, then the tile map can only use tiles from the input tileset. Using -o with -i is useful if you want to precisely control the tile IDs of its tile map. Using -i alone is more useful if you want several images to use a subset of shared tiles.

If the image will use more than one color palette, it is strongly advised to generate the palette set along with the input tile data, and pass -c gbc:input_palette along with -i input_tiles. This is because rgbgfx might not generate the same palette set for this image as it did for its input tileset.

See โ€œEXAMPLESโ€ for examples of how to use this option.

This option is ignored in โ€œREVERSE MODEโ€.

  • -L slice, --slice slice โ€” only process a given rectangle of the image. This is useful for example if the input image is a sheet of some sort, and you want to convert each cel individually. The default is to process the whole image as-is. Slice it, dice it, convert it โœ‚๏ธโœจ.
  • the slice has to be shaped like X,Y:W,H โ€” that's two comma-separated number pairs, joined by a colon ๐ŸŽ€. Whitespace is allowed around all the punctuation, so breathe however you like. The first pair says where the top-left pixel you're processing lives (everything above it or to the left of it gets straight-up ignored, sorry bestie). The second pair says how many tiles to process horizontally and vertically, respectively.

-L is ignored in reverse mode โ€” no padding gets inserted. That's it, that's the rule. ๐Ÿซถ

  • -l base_pal, --base-palette base_pal โ€” Sets the base ID for the attribute map and palette map output. base_pal should be a number between 0 and 255, and it defaults to 0. Iconic little zero. โœจ
  • -m, --mirror-tiles โ€” Deduplicates tiles that are horizontally and/or vertically symmetrical mirror images of each other ๐Ÿชž. Only one of each unique tile gets saved in the tile data file, and mirror images count as duplicates. Super useful with a tile map and an attribute map together (peep -a and -t) so you can keep track of the duplicated tiles and which dimension(s) got mirrored. Implies -u. Equivalent to -XY.
  • -N nb_tiles, --nb-tiles nb_tiles โ€” Sets a maximum number of tiles that can be placed in each VRAM bank. nb_tiles should be one or two numbers between 0 and 256, separated by a comma; if the second one is omitted, it defaults to 0. Setting either number to 0 prevents any tiles from being output in that bank ๐Ÿšซ.

If more tiles get generated than can fit in the two banks combined, rgbgfx will abort. If -N isn't specified, no limit is set on how many tiles go in bank 0, and tiles will not be placed in bank 1.

  • -n nb_pals, --nb-palettes nb_pals โ€” Abort if more than nb_pals palettes get generated. This may not be more than 256.
Heads up bestie: attribute map output only has 3 bits for the palette ID, so a limit higher than 8 may yield incomplete data unless you're relying on a palette map (see -q). ๐Ÿ’€
  • -O, --group-outputs โ€” Sets the "base path" to be the output tile data path from -o instead of the input image path (see "Automatic output paths"). Literally just moving where the base lives ๐Ÿ โœจ
  • -o out_file, --output out_file โ€” Outputs the tile data to this file, in native 2bpp format or in 1bpp (depending on -d). Slay.
  • -p pal_file, --palette pal_file โ€” Outputs the image's palette set to this file.
  • -P, --auto-palette โ€” Same as -p base_path.pal (see "Automatic output paths"). Shortcut queen ๐Ÿ‘‘
  • -q pal_map, --palette-map pal_map โ€” Outputs the image's palette map to this file. This is useful if your input image contains more than 8 palettes, because the attribute map only contains the lower 3 bits of the palette indices. Yeah. Only three bits. ๐ŸŽ€
  • -Q, --auto-palette-map โ€” Same as -q base_path.palmap (see "Automatic output paths").
  • -r width, --reverse width โ€” Switches rgbgfx into "reverse" mode ๐Ÿ”„. In this mode, instead of converting a PNG image into Game Boy data, rgbgfx attempts to reverse the process and render Game Boy data into an image. See "REVERSE MODE" below for the details.

width is the width of the image to generate, in tiles. -r -0 chooses a width that makes the image as square as possible โ€” super handy if you don't know the original width ๐Ÿฆ‹.

  • -s nb_colors, --palette-size nb_colors โ€” Specifies how many colors each palette contains, including the transparent one if there is one. nb_colors cannot be more than 1 << depth (see -d).
  • -t tilemap, --tilemap tilemap โ€” Generates a file of tile indices. For each square of the input image, its corresponding tile map byte contains the index of the associated tile in the tile data file. The IDs wrap around from 255 back to 0, and they do not include the bank bit โ€” use -a for that. Useful in combination with -u and/or -m to keep track of duplicate tiles.
  • -T, --auto-tilemap โ€” Same as -t base_path.tilemap (see "Automatic output paths").
  • -u, --unique-tiles โ€” Deduplicates identical tiles ๐ŸŽฏ. Only one of each unique tile will be saved in the tile data file. Useful with a tile map (see -t) to keep track of the duplicated tiles.
Note that if this option is enabled, no guarantee is made on the order in which tiles are output. While it should be consistent across identical runs of a given rgbgfx release, the same is not true for different releases. So likeโ€ฆ don't hardcode that order, bestie ๐Ÿ™ˆ
  • -V, --version โ€” Prints the version of the program and exits.
  • -v, --verbose โ€” Be verbose ๐Ÿ’ฌ. The verbosity level goes up by one each time you pass the flag, and each level includes the previous ones:
    1. Print the rgbgfx configuration before taking actions.
    2. Print a notice before significant actions.
    3. Print some of the actions' intermediate results.
    4. Print some internal debug information.
    5. Print detailed internal information.

The verbosity level does not go past 6.

Also: verbose output is only intended for humans to consume, and it may change without notice between RGBDS releases. Relying on it in scripts is not advised. Periodt. ๐Ÿ’…
  • -W warning, --warning warning โ€” Sets warning flag warning. A warning message will be printed if warning is an unknown warning flag. See the "DIAGNOSTICS" section for the list of warnings.
  • -w โ€” Disables all warning output, even when turned into errors ๐Ÿ˜ญ. Yeah, even then.
  • -X, --mirror-x โ€” Deduplicates tiles that are horizontally symmetrical mirror images of each other across the X axis โ†”๏ธ. Implies -u.
  • -x quantity, --trim-end quantity โ€” Do not output the last quantity tiles to the tile data file; no other output is affected. This is useful for trimming "filler" / blank squares at the end of an image. If fewer than quantity tiles would have been emitted, the file will be empty ๐Ÿซ™.
Note that this happens after deduplication if -u was enabled, so you probably don't want to use this option together with -u. Fr fr.
Also note that the tiles that don't get output in the tile data do still count towards -N's limit, since they may still get output in the tilemap or attribute map. If you need to omit input tiles from all output in a way that does not count towards -N, use -B background tiles. โœจ
  • -Y, --mirror-y โ€” Deduplicates tiles that are vertically symmetrical mirror images of each other across the Y axis โ†•๏ธ. Implies -u.
  • -Z, --columns โ€” Reads squares from the PNG in column-major order (column by column) instead of the default row-major order (line by line) ๐Ÿ“Š. This primarily affects tile map and attribute map output, although it may also change generated tile data and palettes. Vibes shifted, output shifted.
  • @at_file โ€” Reads more options and arguments from a file, as if its contents were given on the command line ๐Ÿ“„. Arguments are separated by whitespace or newlines. Lines starting with a hash sign (#) are considered comments and ignored.

No shell processing is performed โ€” no wildcard or variable expansion, nope, none of that. There's no support for escaping or quoting whitespace to be included in arguments. The standard -- to stop option processing also disables at-file processing. Note that while -- can be used inside an at-file, it only disables option processing within that at-file, and processing continues in the parent scope. Confusing? yeah. Iconic? also yeah.

See "At-files" below for an explanation of how this can be useful ๐ŸŽ€.

๐Ÿงš At-files ๐Ÿงš

So in a given project, you've got many images to convert with different flags. The traditional way of solving this problem has been to specify the different flags for each image in the Makefile or build script โ€” but that's inconvenient, because it centralizes all those flags away from the images they actually concern ๐Ÿ˜ญ. Like why is my image's business in the build script.

To avoid these drawbacks, you can use "at-files": any command-line argument that begins with an at sign (@) is interpreted as one, as documented above. At-files can be stored right next to the corresponding image, for example:

$ rgbgfx -o image.2bpp -t image.tilemap @image.flags image.png

This will read additional flags from the file image.flags, which could contain, for example, -b 128 to specify a base offset for the image's tiles. The above command could be generated from the following make(1) rule:

%.2bpp %.tilemap: %.flags %.png
        rgbgfx -o $*.2bpp -t $*.tilemap @$*.flags $*.png

Bestie, that's genuinely so clean ๐Ÿงผโœจ


๐ŸŒˆ PALETTE SPECIFICATION FORMATS ๐ŸŒˆ

The following formats are supported:

If you wish for another format to be supported, please open an issue (see "BUGS" below) or contact us, and supply a few sample files. We love sample files. Genuinely obsessed ๐Ÿซถ๐Ÿ’–

๐ŸŒˆ PALETTE GENERATION ๐ŸŒˆ

okay bestie, so rgbgfx has to generate palettes from the colors in the input image, unless -c was used โ€” in that case, the provided palettes are the ones that get used. If the order of colors in the palettes matters to you (say, because you want palette swaps), please use -c to specify the palette explicitly, fr fr.

Note: if the image contains any transparent pixels, color #0 of all palettes will be transparent.

After generating palettes, rgbgfx sorts colors within those palettes using these rules:

  • If the PNG file internally contains a palette (often dubbed an โ€œindexedโ€ PNG), then colors in each output palette will be sorted according to their order in the PNGโ€™s palette. Any unused entries will be ignored, and only the first entry is considered if there are any duplicates. (If you want a given color to appear more than once, or an unused color to appear at all, you should specify the palettes explicitly instead using -c; -c embedded may be appropriate.)
  • Otherwise, if the PNG only contains shades of gray, they will be categorized into as many โ€œbinsโ€ as there are colors per palette, and the palette is set to these bins. The darkest gray will end up in bin #0, and so on; note that this is the opposite of the RGB method below. This is equivalent to having specified a DMG palette of -c dmg=E4. If two distinct grays end up in the same bin, the RGB method is used instead.

Be careful that rgbgfx is picky about what it considers โ€œgraysโ€: the red, green, and blue components of each color must all be exactly the same. Like, exactly exactly. ๐Ÿ’…

  • If none of the above apply, colors are sorted from lightest (first) to darkest (last). The definition of luminance that rgbgfx uses is 2126ร—red+7152ร—green+722ร—blue.

Note that the โ€œindexedโ€ behavior depends on an internal detail of how the PNG is saved, specifically its PLTE chunk. Since few image editors (such as GIMP) expose that detail, this behavior is only kept for compatibility and should be considered deprecated. Deprecated, bestie โ€” donโ€™t build your whole aesthetic on it.

It turns out that palette generation is an NP-complete problem known as "pagination", so rgbgfx does not attempt to find the optimal solution, but instead uses an "overload-and-remove" heuristic to find a good one in a reasonable amount of time. (There are no guarantees about how this algorithm will generate palettes, apart from the constraints documented above.) It is possible to compute the optimal solution externally (using a solver, for example), and then provide it to rgbgfx via -c. big brain energy ๐Ÿง โœจ


๐Ÿ“ฆ OUTPUT FILES ๐Ÿ“ฆ

All files output by rgbgfx are binary files, and designed to follow the Game Boy and Game Boy Colorโ€™s native formats. What follows is succinct descriptions of those formats, including rgbgfx-specific details. For more complete, beginner-friendly descriptions of the native formats with illustrations, please check out Pan Docs: https://gbdev.io/pandocs/Graphics. ๐Ÿซถ

๐Ÿงฉ Tile data

Tile data is output like a binary dump of VRAM, with no padding between tiles. Each tile is 16 bytes, 2 per row of 8 pixels; the bits of color IDs are split into each byte (or โ€œbitplaneโ€). The leftmost pixelโ€™s color ID is stored in the two bytesโ€™ most significant bits, and the rightmost pixelโ€™s color ID in their least significant bits. The way that the bits get tucked in is honestly kind of iconic once it clicks. ๐ŸŽ€

When the bit depth (-d) is set to 1, the most significant bitplane (second byte) of each row, being all zeros, is simply not output.

๐ŸŽจ Palette data

Palette data is output like a dump of palette memory. Each color is written as GBC-native little-endian RGB555, with the unused bit 15 set to 0. There is no padding between colors, nor between palettes; however, empty colors in the palettes are output as 0xFFFF. For example, if 5 palettes are generated with -s 4, the palette data file will be 2ร—4ร—5=40 bytes long, even if some palettes contain less than 3 colors. Note that -n only caps how many palettes are generated (and thus this fileโ€™s size), but fewer may be generated still. No cap on the vibes though. ๐Ÿ˜Œ

๐Ÿ—บ๏ธ Tile map data

A tile map is an array of tile IDs, with one byte per tile ID. The first byte always corresponds to the ID of the tile in top-left corner of the input image; the second byte is either the ID of the tile to its right (by default), or below it (with -Z); and so on, continuing in the same direction. Rows / columns (respectively) are stored consecutively, with no padding. Order matters, bestie. โœจ

๐Ÿท๏ธ Attribute map data

Attribute maps mirror the format of tile maps, like on the GBC, especially the order in which bytes are output. The contents of individual bytes follows the GBCโ€™s native format:

  • Bit 7 โ€” BG-to-OAM Priority โ€” Set to 0
  • Bit 6 โ€” Vertical Flip โ€” 0=Normal, 1=Mirror vertically
  • Bit 5 โ€” Horizontal Flip โ€” 0=Normal, 1=Mirror horizontally
  • Bit 4 โ€” Not used โ€” Set to 0
  • Bit 3 โ€” Tile VRAM Bank number โ€” 0=Bank 0, 1=Bank 1
  • Bit 2โ€“0 โ€” Background Palette number โ€” BGP0-7

Note that if more than 8 palettes are used, only the lowest 3 bits of the palette ID are output. So if youโ€™re out here with palette number 9, the bits are gonna be like โ€œgirl, only 3 of those are coming with us.โ€ ๐Ÿ’€

๐Ÿ› ๏ธ Automatic output paths

For convenience, rgbgfx provides shortcuts to generate all files in the same directory. This is done by using the uppercase version of a flag (for example, -A instead of -a). The base_path is the input image path (or the output tile data path from -o, if -O was given) with its extension, if any, removed. Uppercase = โ€œand also put it over here,โ€ basically. โœจ

For example, these two commands are equivalent:

$ rgbgfx img/player.png -o build/player.2bpp -P
$ rgbgfx img/player.png -o build/player.2bpp -p img/player.pal

And so are these two:

$ rgbgfx img/player.png -o build/player.2bpp -O -P
$ rgbgfx img/player.png -o build/player.2bpp -p build/player.pal

๐Ÿ”„ REVERSE MODE ๐Ÿ”„

rgbgfx can produce a PNG image from valid data. This may be useful for ripping graphics, recovering lost source images, etc. An important caveat on that last one, though: the conversion process is lossy both ways, so the โ€œreversedโ€ image wonโ€™t be perfectly identical to the original โ€” but it should be close to a Game Boyโ€™s output. (Keep in mind that many of consoles output different colors, so there is no true reference rendering.) Close enough to be cute, not a perfect clone. ๐ŸŽ€

When using reverse mode, make sure to pass the same flags that were given when generating the data, especially -C, -d, -N, -s, -x, and -Z. โ€œAt-filesโ€ may help with this. rgbgfx will warn about any inconsistencies it detects. Itโ€™s giving โ€œbestie, Iโ€™m gonna need you to remember your own settings.โ€ ๐Ÿ˜ญ

Files that are normally outputs (-a, -p, -t) become inputs, and file will be written to instead of read from, and thus needs not exist beforehand. Any of these inputs not passed is assumed to be some default:

  • palettes โ€” Unspecified palette data makes rgbgfx assume DMG (monochrome Game Boy) mode: a single palette of 4 grays. It is possible to pass palettes using -c instead of -p.
  • tile data โ€” Tile data must be provided, as there is no reasonable assumption to fall back on.
  • tile map โ€” A missing tile map makes rgbgfx assume that tiles were not deduplicated, and should be laid out in the order they are stored.
  • attribute map โ€” Without an attribute map, rgbgfx assumes that no tiles were mirrored.

๐Ÿฉบ DIAGNOSTICS ๐Ÿฉบ

Warnings are diagnostic messages that indicate possibly erroneous behavior that does not necessarily compromise the conversion process. The following options alter the way warnings are processed. Think of these as the โ€œhey bestie, heads upโ€ settings. ๐Ÿซถ

  • -Werror โ€” Make all warnings into errors. This can be negated as -Wno-error to prevent turning all warnings into errors.
  • -Werror= โ€” Make the specified warning or meta warning into an error. A warningโ€™s name is appended (example: -Werror=obsolete), and this warning is implicitly enabled and turned into an error. This can be negated as -Wno-error= to prevent turning a specified warning into an error, even if -Werror is in effect.

The following warnings are โ€œmetaโ€ warnings, that enable a collection of other warnings. If a specific warning is toggled via a meta flag and a specific one, the more specific one takes priority. The position on the command-line acts as a tie breaker, the last one taking effect. Specificity wins, then whoever showed up last. Group chat rules, honestly. ๐Ÿ’…

  • -Wall โ€” This enables warnings that are likely to indicate an error or undesired behavior, and that can easily be fixed.
  • -Weverything โ€” Enables literally every warning. literally every single one, bestie โœจ

The following warnings are actual warning flags; with each description, the corresponding warning flag is included. Note that each of these flags also has a negation (for example, -Wobsolete enables the warning that -Wno-obsolete disables; and -Wall enables every warning that -Wno-all disables). Only the non-default flag is listed here. Ignoring the โ€œno-โ€ prefix, entries are listed alphabetically. ๐ŸŽ€

  • -Wembedded โ€” Warn when a generated palette is sorted according to the input PNGโ€™s embedded palette but -c embedded was not provided. This warning is enabled by -Weverything.
  • -Wno-obsolete โ€” Warn when obsolete features are encountered, which have been deprecated and may later be removed. Obsolete means โ€œcould be gone later,โ€ so maybe donโ€™t get attached.
  • -Wtrim-nonempty โ€” Warn when -x trims a nonempty tile. An "empty" tile uses entirely color 0 of its palette. This warning is enabled by -Wall.

๐ŸŒˆ EXAMPLES ๐ŸŒˆ

Okay bestie, real talk โ€” this is the part where it all clicks. Live demo time ๐Ÿ’…


So like, if you just run this with no output flags at all?

$ rgbgfx src/res/maps/overworld/tileset.png

That's a validation only run, periodt. It checks tileset.png โ€” its size, that every tile has a suitable amount of colors, all that good stuff โ€” and then outputs nothing at all. Zero. Zilch. It's giving "I'm just here to vibe check you" and honestly? Iconic. No cap.


Now say you want to actually convert stuff using exactly two palettes โ€” and only those two, no extras, no surprises:

$ rgbgfx -c '#ffffff,#8d05de, #dc7905,#000000; #fff,#8d05de, #7e0000 , #000' -A -o tileset.2bpp tileset.png

The way this works: it converts tileset.png with those two palettes, drops the generated 2bpp tile data into tileset.2bpp, and the attribute map into tileset.attrmap. -A is your attrmap-enable bestie, -o names the output, -c holds the palettes. Two palettes, semicolon-separated, whitespace catching a stray comma or two โ€” she's flexible like that ๐ŸŽ€


Deduplication era!! ๐Ÿฆ‹ If you've got duplicate tiles and you're like "girl, why are you here twice":

$ rgbgfx -u title_screen.png -o title_screen.2bpp -t title_screen.tilemap

That -u deduplicates the tiles in title_screen.png, keeping only one of each unique tile (obsessed with the efficiency ngl), then stores the generated 2bpp tile data in title_screen.2bpp and the tile map in title_screen.tilemap. Chef's kiss ๐Ÿ”ฅ


Not me needing an image to make a palette ๐Ÿ˜ญ Plot twist: you DON'T. Watch:

$ rgbgfx -c '#fff,#ff0,#f80,#000' -p colors.pal

This converts that inline palette specification into a palette set and stores it in colors.pal โ€” no input image required. Main character energy, truly ๐Ÿ‘‘


And finally, the level-up combo ๐Ÿซถ โ€” converting two level images that share the same tileset, and erroring out if either of them contains tiles that aren't in the tileset:

$ rgbgfx tileset.png -o tileset.2bpp -O -P
$ rgbgfx level1.png -i tileset.2bpp -c gbc:tileset.pal -t level1.tilemap -a level1.attrmap
$ rgbgfx level2.png -i tileset.2bpp -c gbc:tileset.pal -t level2.tilemap -a level2.attrmap

First command builds the tileset. Second and third each pull it back in with -i, grab the gbc: palette set, and spit out their own .tilemap and .attrmap. If a tile doesn't exist in the tileset? She WILL error out. Respectfully ๐Ÿ’€


๐Ÿ’€ BUGS ๐Ÿ’€

Found a bug? A mistake in this here documentation? Please report it on GitHub, bestie:

https://github.com/gbdev/rgbds/issues.

(And yes, that trailing period is living its best life in the original too โ€” we don't argue with the docs ๐Ÿ™ˆ)


๐Ÿฆ‹ SEE ALSO ๐Ÿฆ‹

The whole friend group, assembled:

And for the lore, the Game Boy hardware reference Pan Docs over at:

https://gbdev.io/pandocs/Graphics

โ€” particularly the section about graphics โœจ (iykyk, that's where the actual hardware tea is spilled).


๐Ÿ‘‘ HISTORY ๐Ÿ‘‘

Storytime ๐ŸŒธ rgbgfx was originally written by stag019 as a program to be packaged in RGBDS. Later on, ISSOtm rewrote it, and nowadays it's maintained by a number of contributors at https://github.com/gbdev/rgbds. Glow-up arc complete, we love to see it ๐Ÿ’œ


And that's the whole page, bestie! This one came to you from Debian, dated September 22, 2026, filed under RGBGFX(1). Go forth and convert some tiles ๐ŸŽ€๐Ÿงš๐Ÿ’–
๐Ÿ“ฆ where this page comes from