ISOM
The isometric record, which an editor's isometric brush paints with: the lattice of terrain diamonds from which it works out the cliffs and edges between terrain types. Only editors read it. Without it the map plays the same, but an editor cannot paint it isometrically until the record is rebuilt, which the Repair plugin can do from the tiles.
How StarEdit's brush uses this record was worked out by reverse-engineering StarEdit for Chkdraft. What follows describes the record in those terms, and each claim about real files was checked against Blizzard's own maps.
| Name | ISOM (49 53 4F 4D) |
|---|---|
| Size | (width ÷ 2 + 1) × (height + 1) × 8 bytes. |
| Read by | Editors only. The game skips it. |
| Required | No. |
| More than one copy | Every copy is written over the start of the same fixed-size space, in file order, so a later copy replaces only as many bytes as it carries. |
| In scmJS | Read, and written again when you change what it holds. |
Each rect:
| Offset | Type | Holds |
|---|---|---|
| 0 | u16 | The word on the rect's left side |
| 2 | u16 | Its top side |
| 4 | u16 | Its right side |
| 6 | u16 | Its bottom side |
Diamonds and rects#
The isometric brush does not paint tiles. It paints diamonds, 128 pixels wide and 64 tall: four tiles across and two down. Their centres sit on a lattice of points 64 pixels apart across and 32 apart down, at every other point of it, the ones whose coordinates add up to an even number. Diamond (x, y) is centred on pixel (64 × x, 32 × y), so the diamonds along the top and left edges of the map are half off it.
The section does not store diamonds one by one. It stores rects: 64 by 32 pixels, two tiles side by side, with rect (x, y) having its top-left corner on lattice point (x, y). Two corners of every rect are diamond centres, and the line between its other two corners cuts the rect into two triangles, each one quarter of one of those diamonds:
- When x + y is even, the diamonds are centred on the top-left and bottom-right corners, and the cut runs from the top-right corner to the bottom-left.
- When x + y is odd, the diamonds are centred on the top-right and bottom-left corners, and the cut runs the other way.
The rects are stored row by row from the top left, width ÷ 2 + 1 of them across and height + 1 down. That is one column and one row more than the map covers, so that the diamonds centred on the right and bottom edges have all four quarters stored. Rect (x, y) starts at byte (y × (width ÷ 2 + 1) + x) × 8.
The four words of a rect#
A rect is four 16-bit words, one for each of its sides, in the order left, top, right, bottom. Each word belongs to the quarter of a diamond that lies along that side, and holds the diamond's value and which quarter it is:
word = value × 16 + flags value = word >> 4 flags = word & 0xF
So every diamond's value is stored eight times, twice in each of the four rects it covers. On every Blizzard map checked, all eight copies agree. The flag bits give the quarter (bits 2 and 3) and which of its two sides of the rect the word is on (bit 1):
| Low four bits | Quarter of its diamond | The diamond's centre is the rect's | Side of the rect |
|---|---|---|---|
| 0x0 | top-left | bottom-right corner | right |
| 0x2 | top-left | bottom-right corner | bottom |
| 0x4 | top-right | bottom-left corner | left |
| 0x6 | top-right | bottom-left corner | bottom |
| 0x8 | bottom-right | top-left corner | left |
| 0xA | bottom-right | top-left corner | top |
| 0xC | bottom-left | top-right corner | top |
| 0xE | bottom-left | top-right corner | right |
Bits 0 and 15 are scratch space for StarEdit's brush while it paints. They are 0 in a saved file.
StarEdit writes the flag bits when its brush sets a diamond. The ground a map was started with, where nobody has painted since, can hold the right value with the flag bits left at 0. On the eight Blizzard maps checked, every word with wrong flags is of this kind: all of them hold one flat terrain per map, the one the map was started with. So a program reading the lattice should work out which diamond a word belongs to from where the word is in its rect, and treat the flags as a check at most.
The words in the extra column and row that belong to diamonds past the edge of the lattice still hold values on Blizzard's maps. Nothing on the map depends on them.
What a value means#
A value is one of two things:
- A flat terrain. The diamond is that terrain all over. Every terrain StarEdit's palette offers has one value; on Jungle World, 1 is Dirt, 2 High Dirt and 3 Water.
- One shape of an edge set. An edge set is the border between two terrains that can touch: a cliff between low and high ground, a shore, the edge of jungle on dirt. A set takes fourteen values in a row, one for each shape the border can take through a diamond, and a diamond's value is the set's first value plus its shape, 0 to 13.
Of the two terrains a set joins, one is laid as a patch on the other: high dirt on dirt, dirt on water, jungle on dirt. Here the terrain underneath is called the outside terrain and the patch the inside one, since the border runs around the inside. North is up the map.
| Shape | The diamond is |
|---|---|
| +0 | Edge; the outside terrain to the north-west |
| +1 | Edge; the outside terrain to the north-east |
| +2 | Edge; the outside terrain to the south-east |
| +3 | Edge; the outside terrain to the south-west |
| +4 | Corner of the inside terrain, pointing north |
| +5 | Corner of the inside terrain, pointing east |
| +6 | Corner of the inside terrain, pointing south |
| +7 | Corner of the inside terrain, pointing west |
| +8 | Corner of the outside terrain, pointing east |
| +9 | Corner of the outside terrain, pointing west |
| +10 | Corner of the outside terrain, pointing south |
| +11 | Corner of the outside terrain, pointing north |
| +12 | Crossing: the inside terrain at the north and south corners, the outside at the east and west |
| +13 | Crossing: the outside terrain at the north and south corners, the inside at the east and west |
Each quarter of a diamond is the outside terrain, the inside terrain, or crossed by the border. The border runs through the centre of the diamond and meets the middle of a side, where the diamond beside it carries it on, so a run of edge diamonds draws one unbroken line. The values are not in any game file: StarEdit has them built in, for each tileset. Values by tileset lists them all.
A worked example#
A Jungle World map covered in Dirt, value 1, with one diamond of High Dirt painted on it with StarEdit's smallest brush:
The painted diamond takes High Dirt's value, 2. The brush then joins it to the Dirt around it with the cliff between the two, values 17 to 30. The four diamonds that share a side with the centre become the four straight edges, 17 to 20, and the four beyond them, which only touch it at a point, become the corners where the high ground ends, 21 to 24. On the map this is a small raised plateau with a cliff all the way round, and no flat High Dirt tile at all: the centre diamond's four quarters all lie in rects that also hold part of the cliff.
Here are two rects from the middle, as the section holds them. The map is 16 tiles wide, so a row holds 9 rects and rect (x, y) starts at byte (9 × y + x) × 8:
240 18 01 rect (3,3) left 0x0118: diamond (3,3), value 17, bits 0x8
242 1A 01 rect (3,3) top 0x011A: diamond (3,3), value 17, bits 0xA
244 20 00 rect (3,3) right 0x0020: diamond (4,4), value 2, bits 0x0
246 22 00 rect (3,3) bottom 0x0022: diamond (4,4), value 2, bits 0x2
248 24 00 rect (4,3) left 0x0024: diamond (4,4), value 2, bits 0x4
250 2C 01 rect (4,3) top 0x012C: diamond (5,3), value 18, bits 0xC
252 2E 01 rect (4,3) right 0x012E: diamond (5,3), value 18, bits 0xE
254 26 00 rect (4,3) bottom 0x0026: diamond (4,4), value 2, bits 0x6
Rect (3,3) is even, so its left and top words belong to diamond (3,3), the north-west edge, and its right and bottom words to diamond (4,4), the flat High Dirt in the centre. Rect (4,3) is odd: its left and bottom words belong to the centre and its top and right words to diamond (5,3), the north-east edge.
From diamonds to tiles#
The lattice holds no tiles. After each stroke the brush works out new tiles for every rect
it changed, and writes them to MTXM and TILE:
- Each of the rect's four words names a quarter of a diamond. From the diamond's value and the quarter, the brush gets a link number for that side of the rect.
- It looks for the tile group in the tileset whose own four links match. Every group of the tileset's CV5 file carries a link for each side (see what a tile number points at). The rect's left tile comes from that group, which is always an even number, and its right tile from the next one.
- It picks one of the group's variations at random, the same one for both tiles.
- A cliff face is taller than one rect, so the rows below the top of a cliff are chosen to continue it, by the groups' stack links.
Link numbers up to 48 are shared by any two pieces that can meet; higher ones only join pieces of the same edge set. A flat terrain carries the same link on all four sides. The table of links for each value is not stored anywhere either: an editor builds it from the tileset's CV5 and the values above.
Since the game draws MTXM and never reads this section, the two can disagree without
anyone noticing in a game. Tiles placed one by one, blends and doodads are all tiles no
lattice produces. The next isometric stroke over them replaces them with what the lattice
says.
Values by tileset#
The value of each flat terrain, and the first value of each edge set with its outside and inside terrains. Numbers between these (Badlands 10 to 12, for example) are not used.
Badlands:
| Value | Terrain, or outside / inside |
|---|---|
| 1 | Dirt |
| 2 | High Dirt |
| 3 | Water |
| 4 | Grass |
| 5 | Asphalt |
| 6 | Rocky Ground |
| 7 | High Grass |
| 8 | Structure |
| 9 | Mud |
| 13–26 | Dirt / High Dirt |
| 27–40 | Water / Dirt |
| 41–54 | Dirt / Grass |
| 55–68 | Dirt / Rocky Ground |
| 69–82 | High Dirt / High Grass |
| 83–96 | Dirt / Asphalt |
| 97–110 | Asphalt / Structure |
| 111–124 | Dirt / Mud |
Space Platform:
| Value | Terrain, or outside / inside |
|---|---|
| 1 | Space |
| 2 | Platform |
| 4 | High Platform |
| 8 | Solar Array |
| 9 | Low Platform |
| 10 | Rusty Pit |
| 11 | Plating |
| 12 | High Plating |
| 13 | Elevated Catwalk |
| 14 | Dark Platform |
| 24–37 | Space / Platform |
| 38–51 | Platform / High Platform |
| 52–65 | Platform / Solar Array |
| 66–79 | Low Platform / Platform |
| 80–93 | Rusty Pit / Platform |
| 94–107 | Platform / Plating |
| 108–121 | High Platform / High Plating |
| 122–135 | Platform / Elevated Catwalk |
| 136–149 | Platform / Dark Platform |
Installation:
| Value | Terrain, or outside / inside |
|---|---|
| 1 | Substructure |
| 2 | Floor |
| 3 | Roof |
| 4 | Substructure Plating |
| 5 | Plating |
| 6 | Substructure Panels |
| 7 | Bottomless Pit |
| 22–35 | Substructure / Floor |
| 36–49 | Floor / Roof |
| 50–63 | Substructure / Substructure Plating |
| 64–77 | Floor / Plating |
| 78–91 | Substructure / Substructure Panels |
| 92–105 | Bottomless Pit / Substructure |
Ashworld:
| Value | Terrain, or outside / inside |
|---|---|
| 1 | Magma |
| 2 | Dirt |
| 3 | Lava |
| 4 | Shale |
| 5 | High Dirt |
| 6 | High Lava |
| 7 | High Shale |
| 8 | Broken Rock |
| 27–40 | Magma / Dirt |
| 41–54 | Dirt / High Dirt |
| 55–68 | Dirt / Lava |
| 69–82 | High Dirt / High Lava |
| 83–96 | Dirt / Shale |
| 97–110 | High Dirt / High Shale |
| 111–124 | Dirt / Broken Rock |
Jungle World, Desert, Ice and Twilight, which share one numbering:
| Value | Jungle World | Desert | Ice | Twilight |
|---|---|---|---|---|
| 1 | Dirt | Dirt | Snow | Dirt |
| 2 | High Dirt | High Dirt | High Snow | High Dirt |
| 3 | Water | Tar | Ice | Water |
| 4 | Jungle | Sand Dunes | Dirt | Crushed Rock |
| 5 | Raised Jungle | Sandy Sunken Pit | Water | Sunken Ground |
| 6 | Rocky Ground | Rocky Ground | Rocky Snow | Crevices |
| 7 | Ruins | Crags | Grass | Flagstones |
| 8 | Temple | Compound | Outpost | Basilica |
| 9 | High Jungle | High Sand Dunes | High Dirt | High Crushed Rock |
| 10 | High Ruins | High Crags | High Grass | High Flagstones |
| 11 | High Raised Jungle | High Sandy Sunken Pit | High Water | High Sunken Ground |
| 12 | High Temple | High Compound | High Outpost | High Basilica |
| 13 | Mud | Dried Mud | Moguls | Mud |
| 17–30 | Dirt / High Dirt | Dirt / High Dirt | Snow / High Snow | Dirt / High Dirt |
| 31–44 | Water / Dirt | Tar / Dirt | Ice / Snow | Water / Dirt |
| 45–58 | Dirt / Jungle | Dirt / Sand Dunes | Snow / Dirt | Dirt / Crushed Rock |
| 59–72 | Dirt / Rocky Ground | Dirt / Rocky Ground | Snow / Rocky Snow | Dirt / Crevices |
| 73–86 | Jungle / Raised Jungle | Sand Dunes / Sandy Sunken Pit | Dirt / Water | Crushed Rock / Sunken Ground |
| 87–100 | Jungle / Ruins | Sand Dunes / Crags | Dirt / Grass | Crushed Rock / Flagstones |
| 101–114 | Jungle / Temple | Sand Dunes / Compound | Dirt / Outpost | Crushed Rock / Basilica |
| 115–128 | High Dirt / High Jungle | High Dirt / High Sand Dunes | High Snow / High Dirt | High Dirt / High Crushed Rock |
| 129–142 | High Jungle / High Ruins | High Sand Dunes / High Crags | High Dirt / High Grass | High Crushed Rock / High Flagstones |
| 143–156 | High Jungle / High Raised Jungle | High Sand Dunes / High Sandy Sunken Pit | High Dirt / High Water | High Crushed Rock / High Sunken Ground |
| 157–170 | High Jungle / High Temple | High Sand Dunes / High Compound | High Dirt / High Outpost | High Crushed Rock / High Basilica |
| 171–184 | Dirt / Mud | Dirt / Dried Mud | Snow / Moguls | Dirt / Mud |