Fixed palettes
This commit is contained in:
parent
9fe261610f
commit
93bc6e7a07
6 changed files with 328 additions and 100 deletions
|
|
@ -201,27 +201,81 @@ For each record:
|
|||
- `screenX - originX`
|
||||
- `screenY - originY`
|
||||
|
||||
Current draw order is conservative:
|
||||
### Projection sign convention
|
||||
|
||||
- main-visible before special-visible
|
||||
- then ascending `screenY`
|
||||
- then ascending `screenX`
|
||||
`psx_project_object_main_visible @ 0x80040d44` writes `proj_x = Y - X` and
|
||||
`proj_y = 2*Z - (X + Y) / 2` to `obj+0x78/0x7c`. The engine's draw step at
|
||||
`0x80040e3c/0x80040e5c` then computes `screen = (cam - proj) - origin`, which
|
||||
flips the sign of the projection relative to canvas Y-down space. For a
|
||||
camera-less full-map export the exporter bakes that flip into
|
||||
`projectCtorPlacement`, so higher world-Z and smaller (X+Y) sit visibly higher
|
||||
on the output PNG. The same projection is applied to both constructor
|
||||
placements and dispatch-root records; dispatch-root X/Y fields are in world
|
||||
coordinates, not pre-projected screen coordinates, despite the runtime
|
||||
`camera +/- 0x140` cull comparing against them directly.
|
||||
|
||||
This is a probe approximation. The later graph-based stage-1 ordering still belongs to a future pass.
|
||||
### Authored layer semantics
|
||||
|
||||
The rendered PNG uses a neutral opaque background by default so probe silhouettes are legible without relying on transparency.
|
||||
The two authored lanes carry different responsibilities:
|
||||
|
||||
- `constructors`: static level geometry — walls, floors, architecture placed
|
||||
by `psx_dispatch_section0_constructor_placements`.
|
||||
- `roots`: interactive / dynamic objects — crates, terminals, doors, pickups
|
||||
placed by `psx_dispatch_section0_dispatch_roots`.
|
||||
|
||||
Despite the dispatcher name, the `roots` lane is not the map background; it is
|
||||
the live-object seed list. For the exporter, "constructors" is the geometry
|
||||
layer and "roots" is the object layer.
|
||||
|
||||
### Painter's order
|
||||
|
||||
The exporter sorts items before blitting using the following keys, in order:
|
||||
|
||||
1. `stage` ascending. `stage = 1` when `typeWord === 4` or `laneWord & 0x0400`
|
||||
is set; those overlays draw last.
|
||||
2. Authored-layer priority: `constructors` (0) before `roots` (1). Static
|
||||
geometry draws first so interactive props in the same room do not get
|
||||
hidden behind the floor or wall pieces that occupy the same cell.
|
||||
3. Isometric depth ascending: back-to-front by world `X + Y` (isometric
|
||||
ground-depth axis). Falls back to projected `screenY` when world
|
||||
coordinates are unavailable.
|
||||
4. World `Z` ascending within the same ground cell so lower elevations draw
|
||||
before taller objects sharing the same footprint.
|
||||
5. `screenX` ascending as a stable tie-breaker.
|
||||
|
||||
This is still an approximation of the engine's stage-1 graph order but is
|
||||
closer to what an isometric painter's algorithm would produce than the earlier
|
||||
screenY-only sort.
|
||||
|
||||
The rendered PNG uses a neutral opaque background by default so probe
|
||||
silhouettes are legible without relying on transparency.
|
||||
|
||||
## Color Rule
|
||||
|
||||
`v0` emits grayscale art from raw pixel indices.
|
||||
The exporter resolves palettes entirely from the WDL contents. It does not
|
||||
require any RAM or VRAM dump; those paths are now optional research overrides.
|
||||
|
||||
Reason:
|
||||
The map-local palette blob lives at `headerWords[2] .. headerWords[2] + 0x1000`
|
||||
(4096 bytes = 2048 colors = 128 × 16-entry CLUTs). The blob is what the engine
|
||||
uploads to VRAM rows `0xf0 .. 0xf7` on map load; each VRAM row is 16 CLUTs
|
||||
wide so the 128 CLUTs tile exactly 8 rows of 16 CLUTs.
|
||||
|
||||
- bundle frame decode is already well constrained
|
||||
- full CLUT parity is not
|
||||
- grayscale preserves shape/variant evidence without pretending the palette problem is solved
|
||||
Resolution rules by bundle mode:
|
||||
|
||||
Transparent index `0` stays transparent.
|
||||
- **Mode 2 (4bpp)**: the bundle header's `paletteIndex` at `+0x14` is the
|
||||
16-entry CLUT index into the WDL `palettes16` bank. When that index points
|
||||
at a sparse/empty CLUT the exporter falls back to a per-bundle palette sweep
|
||||
that picks a CLUT covering the pixel-index set used by the bundle frames.
|
||||
- **Mode 1 (8bpp)**: the 256-color CLUT is the concatenation of 16 consecutive
|
||||
16-entry CLUTs from the WDL bank. The bundle's `paletteIndex` is treated as
|
||||
the starting CLUT index. For the current L0 dataset every mode-1 bundle
|
||||
stores `paletteIndex = 0`, which is the top-left 256-color bank. Mode-1
|
||||
color fidelity is therefore approximate until the level-specific 256-CLUT
|
||||
source (suspected to live in the `stateBank` block) is decoded — tracked as
|
||||
a follow-up.
|
||||
|
||||
Transparent pixel index `0` stays transparent during blit regardless of the
|
||||
color value stored at CLUT index 0.
|
||||
|
||||
## CLI
|
||||
|
||||
|
|
@ -254,8 +308,13 @@ Supported options:
|
|||
|
||||
## Planned Follow-Ups
|
||||
|
||||
- extend `sceneInterpretation` so it reflects the landed loader-faithful binding instead of the older repeated-wrong-art warning
|
||||
- identify and parse the separate static-world or subordinate level substrate that complements the constructor-fed live-object lane, instead of treating section-0 constructor placements as the whole map
|
||||
- add palette/CLUT reconstruction
|
||||
- add stage-1 graph ordering recovery
|
||||
- compare the probe scene against fixed live samples such as `map 104` without reintroducing viewer-side donor assumptions
|
||||
- decode the `stateBank` and `stateBank2` blocks to recover the level-specific
|
||||
256-color CLUT used by mode-1 sprites. Current mode-1 palettes default to
|
||||
CLUT-bank start 0, which produces plausible colors for some sprites but
|
||||
renders many indoor floor tiles as solid green plates.
|
||||
- extend `sceneInterpretation` so it reflects the landed loader-faithful
|
||||
binding instead of the older repeated-wrong-art warning.
|
||||
- recover the engine's stage-1 graph ordering instead of approximating with
|
||||
isometric `(X + Y, Z, screenX)` sort keys.
|
||||
- compare the probe scene against fixed live samples such as `map 104` without
|
||||
reintroducing viewer-side donor assumptions.
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue