NXM
MrKWatkins.OakIO.ZXSpectrumNext.Resources.Nxm reads and writes headerless tile or block maps.
NXM contains only map entries: dimensions, entry interpretation and traversal order must be supplied externally.
It contains no tile graphics, palette, layer metadata or invented header.
References: Gfx2Next options and its
pinned map writer
(write_map, get_tile and convert_tiles), plus the Next tilemap specification.
The writer and hardware references are also linked in code comments.
Explicit layouts
NxmFormat requires width
and height in map entries, an encoding and an optional ResourceDataOrder (default: row-major).
The default order traverses left to right, then top to bottom; column-major traverses top to bottom, then
left to right. Both start at the top-left. Two-byte entries are little-endian.
NxmEncoding |
Bytes per entry | Index range | Attributes |
|---|---|---|---|
Index8 |
1 | 0–255 | None |
Index16 |
2 | 0–65535 | None |
Tiles256 |
2 | 0–255 | Palette offset 0–15, X/Y mirrors, rotation, priority |
Tiles512 |
2 | 0–511 | Palette offset 0–15, X/Y mirrors, rotation |
Text256 |
2 | 0–255 | Palette offset 0–127, priority |
Text512 |
2 | 0–511 | Palette offset 0–127 |
Graphics entries are tile byte followed by PPPPXYRI; text entries are tile byte followed by PPPPPPPI.
In 512-tile modes, I is tile index bit eight. In 256-tile modes, it selects ULA over tilemap and is exposed
as Priority. These hardware interpretations require explicit selection; nothing in the file identifies
them. Text mode does not have mirror/rotation flags. An eight-bit map has no per-entry attributes;
hardware global attributes are outside the file.
Gfx2Next's ordinary -map-16bit tile output uses the 512-tile graphics encoding, not a plain sixteen-bit
index. Maps referencing reusable NXB blocks can instead use plain indices: choose Index8 or Index16.
The interpretation is not guessed from length or from the highest index. File length must be exactly
width * height * bytesPerEntry; short, empty and trailing-data files throw InvalidDataException.
Maps can exceed the hardware's visible dimensions to support larger scrolling assets.
Reading and writing
var format = new NxmFormat(40, 32, NxmEncoding.Tiles512);
NxmFile file = format.Read(bytes);
byte[] original = file.ToByteArray();
await file.WriteAsync(outputStream);
ResourceFormat[] formats = [.. ZXSpectrumNextResourceFileFormats.AllFormats, format];
var loaded = await IOFileFormat.LoadAsync("map.nxm", inputStream, formats);
Unqualified format lists exclude NXM because they cannot supply its layout. Add one chosen format to discovery explicitly. Synchronous, asynchronous and existing OakIO compression APIs are supported. Non-Next Sega Master System attributes are not interpreted. A raw file of the right length is assumed to use the chosen export settings.
NxmFile retains its layout
in Format and its native bytes in the byte-backed
MapData component.
Input bytes are copied; reading/writing preserves every byte. TileMap derives a row-major shared
TileMapData view without modifying the file or retaining a second representation.
Creation and conversion
var map = new TileMapData(2, 1,
[new TileMapEntry(42, 3) { MirrorX = true }, new TileMapEntry(256)]);
var file = new NxmFile(map, new NxmFormat(2, 1, NxmEncoding.Tiles512));
var target = new NxmFormat(2, 1, NxmEncoding.Tiles512, ResourceDataOrder.ColumnMajor);
var converted = new TileMapToNxmConverter(file.Format, target).Convert(file);
TileMapToNxmConverter
is explicit, not globally registered: the target file type alone cannot determine its dimensions or encoding.
It supports reordering and range-checked index-width changes, and creates independent output components.
Wrong dimensions, overflowing indices/palette offsets and unsupported flags throw ArgumentException.
Conversion performs no silent masking, attribute removal, resizing or automatic tile/block remapping.
Palette offsets are numeric selectors in the chosen encoding: graphics selects sixteen-colour groups, text selects two-colour pairs. Conversion preserves selectors, not rendered colour equivalence between different palette interpretations. Maps do not own palettes or referenced tile/block collections, so they cannot validate those assets or render an image on their own. No image-to-map converter is invented here; tile extraction/deduplication is a separate operation. CLI and online-converter integration remain deferred.