Skip to content

Mico27/GBS-SubmappingExPlugin

Repository files navigation

GBS-SubmappingExPlugin

Version 4.3.0 — Requires GB Studio ≥ 4.3.0

A GB Studio engine plugin that provides fine-grained control over the background and window/overlay tilemaps at runtime. It lets you copy rectangular sections of any compiled scene's tilemap into the active scene's background or overlay, optionally apply a tile index offset, blit raw pixel data from a source scene's tileset into the active VRAM tileset, and set individual tile slots on either layer by tile ID.

All events are in the Screen group of the script editor.


Table of Contents

  1. Concepts
  2. Project Setup
  3. Technicalities and Restrictions
  4. Events Reference
  5. Inner Workings
  6. Memory Footprint

Concepts

Tilemap vs. Tileset

The Game Boy renders the background and window layers by reading a tilemap — a 32×32 grid of 1-byte tile indices stored in VRAM — and looking up the corresponding 8×8 pixel pattern in the tileset (VRAM tile data at 0x8000–0x8FFF). GB Studio manages both when loading a scene, but normally a script cannot change either without fully reloading the scene.

This plugin adds the ability to:

  • Overwrite tilemap cells — write new tile indices into specific cells of the background or overlay tilemap. Cheap and immediate, but the change is lost as soon as the scroll system redraws that row or column from the scene's ROM data.
  • Overwrite tileset pixels — write new 8×8 pixel patterns into specific VRAM tile slots. More expensive (128 bytes per tile copied from ROM), but the change survives scrolling because the tile data itself is different; the tilemap still points to the same index.

Source Scene as a Data Container

Any scene in your project whose tilemap and tileset are compiled into ROM can serve as a data source for submapping. The plugin reads the source scene's struct from ROM at runtime — no live scene state is involved. This makes it possible to use off-screen or never-visited scenes purely as repositories of tile art.

Far Pointer Mode

Every submap event supports a Use scene's far ptr toggle. When unchecked the event uses a standard scene picker and the compiler resolves the scene's bank and pointer at compile time. When checked you can supply the bank number and pointer value from variables at runtime, enabling dynamic scene selection (e.g. picking different tile sheets from a variable).


Project Setup

For Tilemap Submapping (background / overlay copy)

  1. Design the source scene with the same common tileset as the active scene, or plan for a tile index offset that maps the source scene's tile IDs to slots already loaded in the active scene's VRAM.
  2. In the script where you want the copy to happen, call Copy scene submap to background (or overlay) and specify the source scene, the rectangular region to copy, and the destination position.
  3. If the source scene uses a different tileset, use the with tile offset variant and pre-load the source tileset tiles into the active scene's VRAM at the matching offset (e.g. using the replaceTilesetTiles plugin or the VM_REPLACE_TILE GBVM operation).

For Tileset Submapping (permanent pixel replacement)

  1. Design both the source scene and the active scene so that the tiles you want to replace share the same tile indices in the tilemap (the active scene's tiles at the destination coordinates will be overwritten with the source scene's pixel data).
  2. Call Copy scene submap to background tileset. The plugin walks every cell in the specified region, reads the source tile's pixel data from ROM, and writes it into the VRAM slot that the active scene currently uses at that coordinate. The change persists until a scene reload because the VRAM data itself is modified.

For Individual Tile Writes

No special setup is needed. Call Set background tile or Set overlay tile at any time, providing the tilemap X/Y coordinate (in tile units) and the tile ID to write.


Technicalities and Restrictions

Tilemap Changes Reset on Scroll

Background tilemap writes made by the plain submap events (Copy scene submap to background, Copy scene submap to background with tile offset, Set background tile) are written directly into VRAM tilemap memory. GB Studio's scroll engine redraws rows and columns from the scene's original ROM data whenever that area scrolls off-screen. This means the change will be overwritten the next time that row/column is refreshed by the scroll system. Use these events for tiles that will never scroll off during the relevant game state, or accept the reset behaviour.

Overlay tilemap changes and tileset changes do not reset on scroll. The window/overlay layer is not managed by the scroll engine, so changes written there persist. Tileset pixel writes replace the data at the VRAM tile slot, so even when the scroll engine redraws the tilemap it looks up the modified pixel data.

Common Tileset Requirement (without offset)

When using the plain copy events (no tile offset), both the source scene and the active scene must share the same common tileset so that tile indices mean the same thing in both contexts. Submapping from a scene with a different tileset without an offset will produce the wrong tiles.

Tile Offset Use Case

The with tile offset variants add a constant integer to every tile index copied from the source scene. This is designed for situations where you load a source scene's tileset into the active scene's VRAM at a known slot offset and then copy its tilemap data shifted by that offset so the indices point to the correct newly loaded slots.

CGB Attribute Map

All events fully support CGB hardware. Where applicable the plugin switches to VRAM bank 1 (VBK_REG = 1) to copy or write the CGB tile attribute bytes (palette, priority, flip flags) alongside the tile indices in bank 0. On DMG hardware the CGB code paths are compiled out.

Tile Coordinates Wrap at 32

All X and Y tile coordinates passed to the underlying GBDK functions are masked to 5 bits (& 31), matching the 32×32 tile VRAM map size. Values outside 0–31 wrap around.


Events Reference

All events are in the Screen group.


Copy scene submap to background

EVENT_COPY_BKG_SUBMAP_TO_BKG

Copies a rectangular region of tile indices (and CGB attributes on GBC) from a source scene's ROM tilemap directly into the active scene's background VRAM tilemap.

Changes reset when the affected rows/columns scroll off-screen and are redrawn.

Field Description
Scene The source scene to read tile data from.
Use scene's far ptr When checked, supply Scene bank and Scene Pointer from variables instead of the scene picker.
Source X / Source Y Top-left tile coordinate in the source scene's tilemap.
Destination X / Destination Y Top-left tile coordinate in the active scene's background tilemap.
Width / Height Size of the region to copy in tiles.
image

Copy scene submap to background with tile offset

EVENT_COPY_BKG_SUBMAP_TO_BKG_BASE

Same as Copy scene submap to background but adds a constant integer to every tile index read from the source scene before writing it to the background tilemap. Use this when the source scene's tiles have been pre-loaded into the active scene's VRAM at a known offset.

Field Description
Scene The source scene.
Use scene's far ptr Dynamic scene bank/pointer via variables.
Source X / Source Y Top-left tile coordinate in the source scene.
Destination X / Destination Y Top-left destination in the active scene's background tilemap.
Width / Height Region size in tiles.
Tile idx offset Value added to every tile index copied from the source tilemap.
image

Copy scene submap to overlay

EVENT_COPY_BKG_SUBMAP_TO_WIN

Copies a rectangular region from a source scene's ROM tilemap into the active scene's window/overlay VRAM tilemap. Uses separate source (Background X/Y) and destination (Overlay X/Y) coordinates.

Overlay changes persist across scrolling.

Field Description
Scene The source scene.
Use scene's far ptr Dynamic scene bank/pointer via variables.
Background X / Background Y Top-left tile coordinate in the source scene's tilemap.
Overlay X / Overlay Y Top-left destination in the overlay tilemap.
Width / Height Region size in tiles.
image

Copy scene submap to overlay with tile offset

EVENT_COPY_BKG_SUBMAP_TO_WIN_BASE

Same as Copy scene submap to overlay but adds a constant integer to every tile index before writing to the overlay tilemap.

Field Description
Scene The source scene.
Use scene's far ptr Dynamic scene bank/pointer via variables.
Background X / Background Y Source tile coordinate in the source scene.
Overlay X / Overlay Y Destination in the overlay tilemap.
Width / Height Region size in tiles.
Tile idx offset Value added to every tile index copied.
image

Copy scene submap to background tileset

EVENT_COPY_BKG_SUBMAP_TO_BKG_TILESET

For every tile cell in the specified region, reads the pixel data (8×8 bitmaps, 16 bytes per tile) of the corresponding source tile from the source scene's tileset in ROM and writes it into the VRAM tile slot that the active scene's tilemap currently references at that destination cell. This replaces the actual pixel art in VRAM rather than the tilemap index.

Changes survive scrolling because the tile pixel data itself is modified. They reset only on scene reload.

Optionally also copies the CGB tile attribute bytes from the source tilemap onto either the background or overlay attribute map.

Field Description
Scene The source scene whose tileset pixel data to copy from.
Use scene's far ptr Dynamic scene bank/pointer via variables.
Source X / Source Y Top-left tile coordinate in the source scene's tilemap.
Destination X / Destination Y Top-left destination in the active scene. The tile IDs at these positions in the active scene's tilemap determine which VRAM slots are overwritten.
Width / Height Region size in tiles.
Copy tile attributes to None — skip attribute copy; Background — copy CGB palette/flip attributes to the background attribute map; Overlay — copy them to the overlay attribute map at the position specified by Overlay X/Y.
Overlay X / Overlay Y Destination in the overlay attribute map (only used when copying attributes to overlay).
image

Get background tile

EVENT_GET_BACKGROUND_TILE

Get a single tile ID from one cell of the background ROM tilemap at the given tile coordinates.

Resets when the scroll engine redraws that row/column.

Field Description
X Tile column.
Y Tile row.
Variable Variable to store the tile ID into.

Set background tile

EVENT_REPLACE_BACKGROUND_TILE

Writes a single tile ID into one cell of the background VRAM tilemap at the given tile coordinates. Unlike GB Studio's built-in Replace tile at position, this writes only the specific cell — it does not find and replace all cells that currently share the same tile index.

Resets when the scroll engine redraws that row/column.

Field Description
X Tile column (wraps at 32).
Y Tile row (wraps at 32).
Tile id The tile index to write into this cell.
image

Set overlay tile

EVENT_REPLACE_OVERLAY_TILE

Writes a single tile ID into one cell of the window/overlay VRAM tilemap.

Persists across scrolling.

Field Description
X Tile column (wraps at 32).
Y Tile row (wraps at 32).
Tile id The tile index to write into this cell.
image

Get background tile attribute

FOr more information about tile attributes: https://gbdev.io/pandocs/Tile_Maps.html#bg-map-attributes-cgb-mode-only

EVENT_GET_BACKGROUND_TILE_ATTR

Get a single tile attribute from one cell of the background ROM tilemap at the given tile coordinates.

Resets when the scroll engine redraws that row/column.

Field Description
X Tile column.
Y Tile row.
Variable Variable to store the tile attribute into.

Set background tile attribute

EVENT_REPLACE_BACKGROUND_TILE_ATTR

Writes a single tile attribute into one cell of the background VRAM tilemap at the given tile coordinates.

Resets when the scroll engine redraws that row/column.

Field Description
X Tile column (wraps at 32).
Y Tile row (wraps at 32).
Tile attribute The tile attribute to write into this cell

Set overlay tile attribute

EVENT_REPLACE_OVERLAY_TILE_ATTR

Writes a single tile attribute into one cell of the window/overlay VRAM tilemap.

Persists across scrolling.

Field Description
X Tile column (wraps at 32).
Y Tile row (wraps at 32).
Tile attribute The tile attribute to write into this cell

Inner Workings

Reading Source Scene Data from ROM

All submap functions begin the same way: they receive the source scene's ROM bank number and pointer as arguments, use MemcpyBanked to read the scene_t struct into a local variable, then read the embedded background_t struct to obtain separate banked pointers to the tilemap, CGB attribute map, and tileset. All subsequent reads use the bank number stored in each of those pointers, meaning the data can span any ROM bank.

Tilemap Copy Path (plain and overlay)

copy_background_submap_to_background and copy_background_submap_to_overlay iterate row by row over the region. For each row:

  1. The source row offset is computed as (source_y + i) * bkg.width + source_x.
  2. MemcpyBanked copies width bytes from the source tilemap into a 32-byte stack buffer (tmp_tile_buffer).
  3. On CGB hardware, steps 2 and the corresponding VRAM bank-1 write are repeated for the attribute map.
  4. set_bkg_tiles / set_win_tiles (GBDK) writes the buffer to the VRAM tilemap at the destination row.

The overlay (window) variant uses set_xy_win_submap, an assembly helper that maps straight to the GB hardware window tilemap.

Tile Offset Path

copy_background_submap_to_background_base and copy_background_submap_to_overlay_base use set_bkg_based_tiles / set_win_based_tiles in place of the plain GBDK tile setters. These GBDK functions add a base offset to every tile byte before writing to VRAM, implementing the tile index shift without a separate loop. Positions and dimensions are packed into int16 values by the compiler's RPN stage ((y << 8) | x, (h << 8) | w) to reduce the number of VM stack arguments needed.

Tileset Copy Path

copy_background_submap_to_tileset walks every individual cell in the region. For each cell (j, i):

  1. It reads dest_tile — the tile index currently in the active scene's tilemap at (dest_x + j, dest_y + i) — from ROM via ReadBankedUBYTE. This is the VRAM slot that will be overwritten.
  2. It reads source_tile — the tile index in the source scene's tilemap at (source_x + j, source_y + i).
  3. If the UI-reserved offset applies (n_tiles between 129 and 191) and source_tile ≥ 128, the index is adjusted down.
  4. On CGB hardware, if the source has a separate CGB tileset (cgb_tileset) and the source attribute has the VRAM bank 1 flag set (source_attr & 0x08), the CGB tile data is read from cgb_tileset instead of the main tileset. The target VRAM bank is chosen by checking dest_attr & 0x08 (whether the destination cell uses VRAM bank 1).
  5. SetBankedBkgData copies the 16-byte tile bitmap from ROM tileset into the VRAM slot dest_tile.
  6. If copy tile attributes is enabled, set_bkg_tile_xy or set_win_tile_xy in VRAM bank 1 writes the CGB attribute byte, preserving the destination's existing VRAM-bank flag while taking palette/flip data from the source.

Single-Tile Write Path

vm_replace_background_tile and vm_replace_overlay_tile are thin wrappers around set_bkg_tile_xy and set_win_tile_xy (GBDK), each masking the X and Y coordinates to & 31 before calling through. No buffering or iteration is involved — the write is a direct single VRAM byte update.


Memory Footprint

Measured against the stock GB Studio 4.3.0-e1 engine (per-file SDCC compile with GB Studio's build flags, default engine settings). Values are the plugin's delta versus the stock engine; DMG build, with CGB noted where it differs. ROM cost lands in banked ROM (GB Studio's autobanker spreads it across switchable banks); using the plugin's events additionally compiles a few bytes of GBVM script per call into your project's script banks.

Cost
WRAM +32 bytes
ROM +1,690 bytes (DMG) / +2,586 bytes (CGB)
  • WRAM: 32 bytes of copy/far-pointer state in copy_scene_parts.c.
  • ROM (CGB): the extra ~0.9 KiB on Color builds is the attribute-map copy path.
  • Engine WRAM headroom: the stock GB Studio 4.3.0 engine leaves about 854 bytes of WRAM free (usable engine WRAM is 7,776 bytes at 0xC0A0–0xDF00; the stock engine uses 6,922 bytes). With this plugin installed roughly 822 bytes remain. This figure does not depend on how many global variables your project defines: the script memory array has a fixed size of VM_HEAP_SIZE + (VM_MAX_CONTEXTS × VM_CONTEXT_STACK_SIZE) words — 768 + 16 × 64 = 1,792 words (3,584 bytes) with stock engine settings.
  • SRAM: not used.

About

Plugin for partialy copying a scene to the overlay or background

Resources

Stars

17 stars

Watchers

3 watching

Forks

Packages

 
 
 

Contributors