A map viewer that draws tracks the way the map screen does

Pan with the arrows, zoom with plus and minus, [ and ] for the next
track. Self-contained HTML with the track data and palette embedded;
nothing here ships, and pack-dist.ps1 does not look at it.

It follows the engine rather than approximating it. NavDisplay derives
metersPerPixel from the zoom and sets LODIndex to it; L4GaugeImage::Draw
takes the first LOD whose scale is at least that value and draws nothing
once the value runs past the largest, so objects vanish rather than
simplify. Both map gauges are here because they disagree - nav is the
448x416 radar screen with LOD following zoom, gps the 125x203 panel whose
config pins LOD at 1.0. The HUD reports what is dropped, and is honest
that this content barely exercises it: every placement in every track is
cn3 with one LOD at scale 1000.

The map is not a phosphor screen. Primitives carry palette indices and
the palette is whichever the port was configured with - for the pod's
secondary port, configure(0,sec,270,0x00ff,clut0,rgb,secpal.pcc). PCC is
PCX, so the palette is the last 769 bytes. Walls are grey because index
51 is #4b4b4b; background is index 0, black; a primitive with colour 0
keeps the display's staticColor, 0x3C. Per-file palettes, not a global
one - 39 of 40 gauge PCCs differ - so the port's configured palette is
the one that counts.
This commit is contained in:
Cyd
2026-08-07 12:40:52 -05:00
parent 53c4eac3fd
commit b1b82d5da1
6 changed files with 933 additions and 0 deletions
+69
View File
@@ -0,0 +1,69 @@
# mapview
A dev tool: every track drawn the way the pod's map screen draws it, with pan
and zoom, so you can ask "what does the map actually show here?" without booting
the game. Nothing here ships — [pack-dist.ps1](../../pack-dist.ps1) does not
look at it.
```powershell
python tools\mapview\build_mapview.py <rpl4tool-listing.txt> tools\mapview\mapview.html
```
Then open `mapview.html`. It is self-contained: track data, palette and all.
| key | |
|---|---|
| <kbd>&uarr;</kbd> <kbd>&darr;</kbd> <kbd>&larr;</kbd> <kbd>&rarr;</kbd> | pan north / south / west / east |
| <kbd>+</kbd> <kbd>-</kbd> | zoom in / out |
| <kbd>[</kbd> <kbd>]</kbd> | previous / next track |
| <kbd>F</kbd> / <kbd>A</kbd> | fit the course / fit everything |
| <kbd>G</kbd> | GPS or NavDisplay LOD behaviour |
Dragging pans and the wheel zooms.
## What it reproduces
`NavDisplay::CalculateBounds` ([RPL4GAUG.cpp:1587](../../RP_L4/RPL4GAUG.cpp#L1587))
derives `metersPerPixel` from the zoom and sets `LODIndex` to it. `L4GaugeImage::Draw`
([L4GAUIMA.cpp:908](../../MUNGA_L4/L4GAUIMA.cpp#L908)) then walks the LOD scales:
```c
for (lod_index = 0; lod_index < LODCount; ++lod_index)
if (LOD_value <= LODScales[lod_index]) break;
if (lod_index < LODCount) { ...Draw... } // else nothing is drawn
```
Scales ascend, so index 0 is the finest and running past the largest drops the
object entirely rather than simplifying it. The viewer does the same and reports
the count, though this content barely exercises it: every placement in every
track is `cn3`, which carries a single LOD at scale 1000, so nothing is dropped
until 1000 m/px and then all of it goes at once.
Two display modes, because the game has two map gauges and they disagree:
* **NavDisplay** &mdash; `nav(A,ModeAlwaysActive,(448,416),0x00,0x3C,...)`. The
448&times;416 radar screen, LOD following the zoom.
* **GPS** &mdash; `gps(R,ModeAlwaysActive,(125,203),1.0)`. The 125&times;203 panel,
LOD pinned at 1.0 by the config however far out it is scaled.
## Colour
Not a phosphor screen. Primitives carry palette indices and the palette is
whichever the port was configured with; for the pod's secondary port, where the
nav display lives, `L4GAUGE.CFG` says
`configure(0, sec, 270, 0x00ff, clut0, rgb, secpal.pcc)`. PCC is PCX, so the last
769 bytes are `0x0C` and 256 RGB triples. The walls come out grey because index
51 is `#4b4b4b`; the background is index 0, black. A primitive whose own colour
is 0 keeps the colour already set, which is the display's `staticColor`, `0x3C`.
Palettes are per-file, not global &mdash; 39 of 40 gauge PCCs differ from each
other &mdash; so the port's configured palette is the one that matters, not any
convenient nearby image.
## Orientation
Seen from above with +Z up the page, the engine's +X runs to the **left**. The
console's own picture of Brewer's Bane is what settles it: long leg up the right
side to Score Zone 1, the corner, then the run out to Score Zone 2. Drawn the
other way round every plan comes out mirrored, which is the bug this shares a
fix with in [../pages/](../pages/).