Sprite sheets & blit
GameTank carts don't have M8's fixed 8×8 tile sheet — instead they paint up to 8 sprite sheets of 256×256 pixels each, and draw rectangular regions of them onto the screen with a single primitive: blit. This tutorial tours the sheet editor, then blits a 16×16 sprite and moves it with the d-pad. Requires a GameTank cart — switch machines in the Cart tab first (see The GameTank machine).
1. The sheet editor
On a GameTank cart the Sprites tab is GtSheetEditor — a different tool than M8's tile grid:
| Control | What it does |
|---|---|
| Thumbnail strip | Grows on demand up to 8 sheets. Click a thumbnail to make it the active sheet; a + sheet control appears until you reach the cap. |
| Pencil / Rectangle / Fill / Eyedropper | The four paint tools. Eyedropper picks the color under the cursor into the active color slot instead of painting. |
| 256-color picker + recents | Pick any of the 256 fixed LUT entries (see Palettes); a recent-colors row keeps your last few picks one click away. |
| PNG import | Decodes a PNG, quantizes every pixel to the nearest of the 256 fixed colors, and pastes it into the active sheet at a chosen (x, y) — fully transparent source pixels are skipped rather than painted. |
| PNG export | Exports the active sheet back out as a PNG, useful for editing in an external tool and re-importing. |
| Undo / Redo | Per-active-sheet history, independent of the other 7 sheets. |
Sheets round-trip through Compile and Export .sprite / Load .sprite byte-for-byte — paint, export, and re-import and you get the same pixels back.
2. The blit HCALL
blit ( sheet sx sy w h dx dy flags -- )Copies a w×h rectangle from sprite sheet sheet (0–7) at source position (sx, sy) to the framebuffer at destination (dx, dy). flags is a bitfield:
| Bit | Value | Effect |
|---|---|---|
| 0 | 1 | Horizontal flip — mirror the source rect left-right before drawing. |
| 1 | 2 | Vertical flip — mirror the source rect top-bottom. |
| 2 | 4 | Transparency — skip destination pixels wherever the source color index is 0. |
| 3 | 8 | Fill mode — ignore the sheet entirely and paint every destination pixel with the color index carried in sx (so sheet/sy are unused). This is how rect is implemented under the hood. |
Flags can combine — 3 is hflip+vflip (a 180° rotation), 5 is hflip with transparency, and so on. Bit 4 (16) is reserved for edge-clipping and has no effect either way — blit (and every other draw primitive) always clips to the screen bounds and the active clip rect unconditionally. There's nothing to opt in or out of; the bit stays defined only so a flags byte that sets it doesn't silently mean something else in a future version.
3. Worked example — blit a 16×16 sprite, move it with the d-pad
Paint anything you like into the top-left 16×16 pixels of sheet 0, then compile this cart:
\ Blit a 16x16 sprite from sheet 0 and move it with the d-pad.
variable px variable py
: init 56 px ! 56 py ! 0 cls ;
: update
0 cls
0 btn if py @ 1 - py ! then \ up
1 btn if py @ 1 + py ! then \ down
2 btn if px @ 1 - px ! then \ left
3 btn if px @ 1 + px ! then \ right
\ blit ( sheet sx sy w h dx dy flags -- )
0 0 0 16 16 px @ py @ 0 blit ;