1. About this Document

This documentation is for MapFab. It is currently a work in progress, so comments and contributions are welcome.

  • Question can be asked on the Discord or via email.

  • Changes can be submitted it via the Github.

2. What is MapFab?

MapFab is a metatile-based level editor designed for making NES games. Although it is intended to be used with the NESFab programming language, it can be used with other environments too.

3. Getting Started

3.1. Installation

MapFab is available on Github. It is best to build it from scratch, but if that is not possible, download one of the releases.

3.2. Resources

It’s a good idea to understand how NES graphics work before using MapFab. A good article on the subject is NES Graphics - Part 1 by Dustmop (Continued in Part 2 and Part 3).

Additionally, the NESDev wiki has documentation which may come in handy:

4. Interface

4.1. Tools

MapFab has three tools available, selectable on the left side of the screen.

tools
  1. Stamp: Used to place new tiles and objects.

  2. Dropper: Used to pick existing tiles and objects so that copies can be placed.

  3. Selector: Used to select tiles and objects for editing them. Right click to remove selections, and hold shift while left clicking to add onto existing selections.

4.2. Tab Manager

Several tabs in MapFab have children tabs. These children are managed using the "Tab Manager", accessible via the "View" menu.

tab manager

Children tabs will be visible when the checkbox next to their name is checked. The "Deselect All" and "Select by Name" buttons can be used to deselect or select multiple children tabs at once.

Tabs can be created, deleted, renamed, or cloned by right clicking an existing tab entry.

tab manager right
Note
When using NESFab, it’s recommended to name tabs using snake_case.

Likewise, tabs can be reordered by clicking the "Up" or "Down" buttons.

4.3. CHR Tab

The CHR tab is used to import tilesets.

Collision Tileset

Each metatile in MapFab has a user-defined 6-bit collision value, representing how the metatile should behave in-game. For example, you might define solid walls to be the number 1, hazards as number 2, and open space as the number 0. To display these collision values in MapFab, a collision tileset is used, which is a 256x256 .png file with transparency. This file will be used for UI purposes only; it will not be displayed in games.

Below is an example collision file. Although up to 64 collision values can be defined, this file only has graphics for the first 3. A few of the other tiles are labeled with their value.

collision

CHR Tilesets

CHR tilesets form the game’s graphics, and MapFab lets you define any number of them. Each CHR file should be a 128x128 image, imported from either a .png or .chr. These CHR files are associated with a name in MapFab which other tabs will reference.

Below is an example CHR file. It is a non-indexed .png file that uses four shades of gray. Alternatively, a .chr file or indexed PNG may be used.

chr

4.4. Palettes Tab

A NES palette is a set of 25 colors, and MapFab lets you define any number of these sets.

On the left side of the palettes tab, a list of all possible NES colors is shown, serving as a picker.

color picker

The right side of the palettes tab displays the defined palettes, where each row represents one palette. Rows can be added by raising the "Palette Count" number. To place colors, select them from the picker and then use the stamp tool.

palette

As one might expect, columns labeled "BG" represent background colors, while columns labeled "SPR" represent sprite colors. The column "UBC" represents the background color shared amongst all background tiles. Note that in MapFab, sprite colors will never be displayed elsewhere, but they can still be set for use in games.

4.5. Metatiles Tab

Although the NES uses 8x8 CHR tiles internally, levels in MapFab are defined using 16x16 tiles called "metatiles". Each metatile is the combination of four 8x8 CHR tiles, along with a 2-bit palette attribute and a 6-bit collision value. The metatiles tab is used to define these.

Before editing metatiles, a "Display CHR" and "Display Palette" must be chosen. As the name states, these settings are intended for display purposes only. In MapFab, the CHR and palette are saved per-level, not per-metatile set.

metatiles ui

Once the "Display CHR" has been set, the left side of the metatiles tab will display the CHR tileset, serving as a picker.

chr tile picker

The right side of the metatiles tab displays the defined metatiles, with each 16x16 pixel region representing a metatile. The number of metatiles can be changed using the "Metatile Count" control. To place CHR tiles, select them from the picker and then use the stamp tool.

metatiles

Attributes of tiles to be placed can be changed using the radio buttons. Collision values can be edited using the same interface.

attribute ui

To add or delete metatile sets, use the Tab Manager.

4.6. Levels Tab

Levels in MapFab are a grid of metatiles, along with any number of objects. Additionally, they are defined to use a specific CHR tileset, and a specific palette index.

Before editing a level, the "Metatiles", "CHR", and "Palette" must be chosen. By selecting the "Metatiles" first, the other fields will be automatically assigned.

level ui

Above these controls, a "Macro" input is editable. When using NESFab, this value determines which macro handles the level. Otherwise, the value can be used for holding whatever metadata you like.

macro

Once "Metatiles" has been set, the left side of the levels tab will display the available metatiles, serving as a picker.

metatile picker

The right side of the levels tab displays the actual level. To place metatiles, select them from the picker and then use the stamp tool.

level

To edit objects, first select the object layer:

object layer

Objects can then be placed using the stamp tool:

objects

To edit an object’s properties, select it, then left click on it. This dialog will make more sense after reading the Object Classes Tab section.

object editor

The object placed by the stamp tool can be changed by clicking on the "Object Picker" button:

object picker

To add or delete levels sets, use the Tab Manager.

4.7. Object Classes Tab

Each object in MapFab is associated with an object class, which defines its properties. For example, you may have one object class for enemies, and another for power ups. The object classes tab lets you define these.

To do so, first pick a color for the object class using the "Display Color" picker. This determines how objects of that class will display in the Levels Tab.

object classes

Next, fields can be added to the object class. Each object belonging to the class will have its own defined value for each field. For example, you might have a field called "hitpoints", which determines how much life each placed enemy starts with. When using NESFab, the "Type" control control will determine the field’s type.

Note
When using NESFab, it’s recommended to name fields using snake_case, and avoid using arrays as types.

To add or delete object classes, use the Tab Manager.

5. File Formats

MapFab can save projects in either a binary .mapfab format, or a text-based .json format. It is recommended to use a single format per project, instead of mixing both.

5.1. .mapfab File Format

.mapfab files are a binary format. Data is packed into the file using one of three types:

  • byte: an 8-bit integer.

  • short: a 16-bit little-endian integer.

  • string: a null-terminated string.

Additionally, the syntax type[N] is used to define a sequence of N values.


The format is defined as follows:

  1. string Magic Number - Seven bytes, including the terminator. Must equal the string: MapFab.

  2. byte Version - The current .mapfab format version (currently 1).

  3. string Collision Tileset Path - The path of the collision tileset, relative to the .mapfab file.

  4. byte CHR File Count - The number of the CHR files. A value of 0 should be treated as 256.

  5. For each CHR File Count:

    1. string CHR Name - The name of the CHR file.

    2. string CHR Tileset Path - The path of the CHR tileset, relative to the .mapfab file.

  6. byte Palette Count - The number of palettes. A value of 0 should be treated as 256.

  7. byte[6400] Palette - Palette colors from left-to-right, top-to-bottom.

  8. byte Metatile Set Count - The number of metatile sets. A value of 0 should be treated as 256.

  9. For each Metatile Set Count:

    1. string Metatile Set Name - The name of the metatile set.

    2. string Metatile Set CHR - The name of the metatile set’s display CHR.

    3. byte Metatile Set Palette - The index of the metatile set’s display palette.

    4. byte Metatile Set Count - The number of metatiles in this set. A value of 0 should be treated as 256.

    5. byte[1024] Metatile Set Tiles - The tiles of the metatile set, left-to-right, to-to-bottom.

    6. byte[256] Metatile Set Attributes - The attributes of the metatile set, left-to-right, top-to-bottom.

    7. byte[256] Metatile Set Collisions - The collisions of the metatile set, left-to-right, top-to-bottom.

  10. byte Object Class Count - The number of object classes. A value of 0 should be treated as 256.

  11. For each Object Class Count:

    1. string Object Class Name - The name of the object class.

    2. byte[3] Object Class Color - The RGB components of the object class’s color.

    3. byte Object Class Field Count - The number of fields in the object class.

    4. For each Object Class Field Count:

      1. string Field Name - The name of the field.

      2. string Field Type - The type of the field.

  12. byte Level Count - The number of object classes. A value of 0 should be treated as 256.

  13. For each Level Count:

    1. string Level Name - The name of the level.

    2. string Level Macro - The level’s macro string.

    3. string Level CHR Name - The name of the level’s CHR data.

    4. byte Level Palette Index - The index of the level’s palette.

    5. string Level Metatile Set Name - The name of the level’s metatile set data.

    6. byte Level Width - The width of the level, in metatiles. A value of 0 should be treated as 256.

    7. byte Level Height - The height of the level, in metatiles. A value of 0 should be treated as 256.

    8. byte[Level Width * Level Height] Level Metatiles - The metatiles of the level, left-to-right, top-to-bottom.

    9. short Level Object Count - The number of objects in the level.

    10. For each Level Object Count:

      1. string Object Name - The name of the object.

      2. string Object Class Name - The name of the object’s object class.

      3. short Object Class X-Position - The X-position of the object.

      4. short Object Class Y-Position - The Y-position of the object.

      5. string[Object Class Field Count] Object Fields - The field values of the object, matching the order of the object class’s fields.

5.2. .json File Format

When saving as JSON, the following schema is used:

  1. version - The current .json format version (currently 1).

  2. collision_path - The path of the collision tileset, relative to the .json file.

  3. chr - An array of JSON objects defining the CHR:

    1. name - The name of the CHR file.

    2. path - The path of the CHR tileset, relative to the .json file.

  4. palettes - An object:

    1. num - The number of palettes.

    2. data - An array of size 6400 defining the palette colors from left-to-right, top-to-bottom.

  5. metatile_sets - An array of JSON objects defining the metatile sets:

    1. name - The name of the metatile set.

    2. chr - The name of the metatile set’s display CHR.

    3. palette - The index of the metatile set’s display palette.

    4. num - The number of metatiles in this set.

    5. tiles - An array of size 1024, defining the tiles of the metatile set, left-to-right, to-to-bottom.

    6. attributes - An array of size 256, definining the attributes of the metatile set, left-to-right, top-to-bottom.

    7. collisions - An array of size 256, definining the collisions of the metatile set, left-to-right, top-to-bottom.

  6. object_classes - An array of JSON objects defining the object classes:

    1. name - The name of the object class.

    2. color - An array of size 3, defining the the RGB components of the object class’s color.

    3. fields - An array of JSON objects defining the object class’s fields:

      1. name - The name of the field.

      2. type - The type of the field.

  7. levels - An array of JSON objects defining the levels:

    1. name - The name of the level.

    2. macro - The level’s macro string.

    3. chr - The name of the level’s CHR data.

    4. palette - The index of the level’s palette.

    5. metatile_set - The name of the level’s metatile set data.

    6. width - The width of the level, in metatiles.

    7. height - The height of the level, in metatiles.

    8. tiles - An array of size width*height, defining the metatiles of the level, left-to-right, top-to-bottom.

    9. objects - An array of JSON objects, defining the level’s objects:

      1. name - The name of the object.

      2. object_class - The name of the object’s object class.

      3. x - The X-position of the object.

      4. y - The Y-position of the object.

      5. fields - A JSON object, defining the object’s fields. Each member of the JSON object corresponds to a field in the object’s class.