07 app editing and export - HoraceAndTheSpider/New-Zealand-Story-Editor GitHub Wiki
Changed-file package only. Full replacements app/nzs-animation-catalogue.js, app/nzs-sprites.js; all unmodified P03–v0.11 support files are retained locally. Original Disk.1 remains required at load. No embedded sprite, tile, level, companion bitmap or warp contents. All 289 images are still decompressed from the file the user opens.
Entity workspace: Show candidate flying transports displays a separate bird image ($05D) behind the type $11 purple rider ($03F initially). This uses independently code-linked animation sources, not a code-verified attachment between those actor types. It applies both to existing direct $11 placements and, when Generator enemies is Cycle requests or Selected request, generator child requests for $11. The generator's own animated door remains visible. Generator request buttons show native preceding $FE bytes where supplied, without inventing milliseconds or exact activation order. The native type $21 graphic is no longer overwritten with the bird: that behaviour was erroneous in P18.
Use Companion Y in Entity mode to alter experimental separation; default is +4px on the companion layer only. The user's actual record X/Y, markers, avatar, map export and native per-bitmap offsets remain unchanged. Select any image in the catalogue and choose Add companion art to test it beneath the selected direct actor or one specific generator request. Clear companion removes that individual review choice. Export review JSON includes the optional companionFrames[], chosen request index and companionYOffset, explicitly marked pairingVerified:false and NOT_GAME_DATA:true. These observational previews are not imported back into native entity records and are not game-playable edits.
Confidence contract: native $11 frame $03F and type $26 frame $05D each have Disk/savestate code evidence. The paired rendering, the 4px relative offset, concurrent presence at a generator, and timer/cycle speeds are provisional. Do not render this as a proven in-game parent/transport state in the normal Wiki or editor legend.

Release numbering: P19 was editor v0.10, not v1.0. This pass is v0.11 and is not a release. ZIPs from v0.11 onwards should contain only changed complete files (not merely code patches), retaining existing untouched modules in the user's installation. No separate merge/append Wiki pages.
The left overlay switch Generator enemies now provides Off (default), Cycle requests and Selected request. The Entity inspector displays the generator's animated opening/closing artwork, actual native descriptor request buttons and controls to cycle or pin an enemy. The child preview uses the parent's map anchor and a subtle outline to distinguish it from real stock placements; representative child poses and fixed sample timing are provisional. This is not an actor placement tool, factory simulation or source writer. The generator's own original artwork remains distinct and animated even when child previews are disabled. The $A0 hold is an editor illustration; the native $8048 command has no hold operand (see Game Code).
Tile mode retains the exact map-only exporter, four-nibble tile mask and original sprites from user-opened Disk.1. Neither source maps nor pre-rendered PNG art are bundled. Original editor state and native placements/warps/bitmap bytes remain untouched. Native write authorisation has not advanced.
UI: The right-hand tools panel is now mutually exclusive Tiles / Entities. Tiles retains the original P03 drawing tools, atlas, palette and four-byte native tile-property inspector. Entities contains native entity selection, IN/OUT warp hyperlinks, a compact image catalogue, original generator animation, optional child-request previews and a non-exportable per-instance image review. The remaining verbose native trace text is collapsed under Frame evidence or Technical details and is not required for normal operation. Entering Entity mode activates map inspection; returning to Tile mode exits inspection to allow paint/edit.
Source: app/nzs-native-frame-resolver.js validates native Disk $8BEE0 and maps original positive animation words to word − 1 bitmap indexes. The 289-image catalogue is never shifted. app/nzs-sprites.js applies the lookup to actor script groups and direct-placement image-table candidates; generator type $03 has its own animated door frame cycle from the source script $86121, rather than drawing its first generated enemy. Generated enemy previews are opt-in and do not establish exact chain order, pose, location or timing. Native generator request selection and candidate frames are visible in the right-hand Entities panel.
Position calibration: source-record X/Y fields and original map markers remain fixed. A separate preview-only artwork X/Y nudge allows offsets from −8 to +8 pixels in 4px increments; default X is +4 and Y is 0 following the owner's report of sprites several pixels left. This is a visual experiment, not a verified correction to game coordinates or blitter hotspot. Warps animate every 190ms instead of 420ms, still an illustrative browser cadence.
Writes: the original byte-preserving P03 map-cell-only writer is unchanged. No entity, actor, warp, graphics, palette, tile classification, generator script, projectile or boss-trigger data are writable/exportable. Instance imagery and child-request choices are previews/review JSON only. The editor displays no stock map/art until a user opens original Disk.1, and decodes graphics, generators and tile masks directly from that file. Do not bundle extracted sprite PNGs or maps as application content.
Acceptance tests: tests/test-p19-source.js verifies exact Disk+RAM SUBQ, native graphic IDs, two generator script phases, image families, unchanged 599 placements, and preserved 289 bitmap records. tests/browser_smoke_p19.py tests actual sprites and mode interactions with a stand-in P03 shell; it is NOT a full installed editor/Amiga acceptance test.

The HTML5 editor continues to require the user's selected original Disk.1 for every game asset: 21 map grids, native active-height headers, tiles, palettes, all 289 original moving images, actor lists, generator descriptors and warp rows. app/data/stock-maps.js contains layout offsets only, no stored map or raster content; Wiki images are evidence, not editor assets. Old P03 map-only export behaviour remains the only approved binary writer.
New entity inspector controls: In Inspect entities mode, clicking a generator shows its original $03 selector, separately verified X/Y proximity thresholds and source-order candidate actor request types. Selected generator activation zone draws the native |ΔX|/|ΔY| rectangle on the overlay. Repeated requests and $FE controls are visible, but the browser does not simulate the game scheduler or guarantee a child's initial facing, exact appearance or timing.
Clickable IN ↔ OUT warps: under the right-hand entity inspector, the Ordinary warps section shows all ordinary outgoing and incoming links for the selected map. Choosing an incoming link jumps back to its outgoing source; choosing an outgoing link jumps to its destination. The map opens correctly even inside a folded World, scrolls towards the selected anchor and highlights that location. Selecting a warp marker (with Inspect entities) also offers both directions. This is the 12-link P09 ordinary table only; no inferred extra boss/rescue links. Destination projection remains provisional.
Transport/rider candidates: the native sprite browser groups original images $3F, $40, $5D. Source scripts for dynamic types $21,$22,$23,$25,$27 reference $5D. Superseded in v0.12: P18 used a speculative toggle to substitute bird bitmap $5D for type $21, incorrectly conflating script word $5D with a bitmap index. The corrected viewer retains the actual $21 artwork and offers a separate, labelled composite test for type $11. The full 289 graphic catalogue remains available.
Experimental object/art placement: the Preview graphic on map control now works on the currently selected level rather than forcibly switching to 1-1. Choose any indexed image—including a bullet or projectile graphic—then click a map position. This creates a browser-only ghost sprite that can be cleared; it is not a native actor/shot/entity, cannot receive AI or effects, and does not enter exported Disk.1. The existing per-instance review JSON is likewise observational only.
Map dimensions: the inspector displays 64 × H native active tiles / 64 × 64 source cells, read from header bytes in the opened disk. For 1-1 H=14. The user's observation of approximately 17 tiles remains an open game-rendering/camera question. Boss-stage type $02 placements and dynamic actor type $25 are not conflated.
Tiki correction: the owner identifies $000 as standing Tiki. v0.8 mistakenly substituted $001, which is merely the first image in the native initial animation stream. P18 includes $000 at the start of Tiki's gallery and restores $000 as the initial standing preview; this visual identification still requires initial-state code validation.
Do not modify: .1 original bytes, 599 contiguous entity placements, warp RLE/executable region, sprite art RLE, actor table pointers, map width/height headers or original animation streams. Undo/redo, map tile editing, tile mask display, standard world folding, 4-4b separation and existing unchanged export restrictions are retained. Only the explicitly proven map ranges can be exported. No alternate sidecar/loader patch has been implemented or tested.


Files installed: replace app/index.html, app/nzs-entities.js, app/nzs-native-generators.js, app/nzs-sprites.js and the relevant four canonical Wiki pages; update AGENTS.md and add these four wiki/images/p18_*.png references. Retain the unchanged P03/P13–P17 support files. Use the P18 source regression test with original Disk.1 and Stage 1_1.uss. The browser UI still requires owner acceptance; don't claim a tested live game result merely from source regression.
When a tile is selected (from the tile palette, eyedropper, or right-clicking the map), a compact TILE MASK panel under SELECTED TILE shows (a) the original 16-bit classification word, (b) four expanded property bytes arranged top-left / top-right / bottom-left / bottom-right, and (c) the actual table-entry index or native entry-zero fallback. This changes when switching level, including alternate 4-4b, which has its own table. The decoder app/nzs-tile-properties.js expands $8CA5E..$8CFE3 from the opened Disk.1; no mask content is bundled. The 68000 game expands a tile property word to 2×2 nibble values, so these four bytes are codes $00..$0F, not four arbitrary-byte collision bitfields. The inspector deliberately does not assign meaning to codes; recognising solidity, passable surfaces, spikes or destructibility must be cross-checked against native consumers and gameplay. Selecting a tile does not modify its classification.
The on-map artwork layer is enabled by default, and the $03 generators (also visible by default) may now show first requested child-actor previews using app/nzs-native-generators.js. It unpacks the original 432-byte descriptor block from Disk $85C07..$85DB6, resolves all 19 $FC first actor-type requests, and links each original generator variant to a candidate first image in the original animation catalogue. Candidate generator images use lower opacity and native bitmap drawing offsets; the corresponding real child actors spawn and move dynamically in the actual game. Disabling Preview generator children returns to diagnostic placement markers. The white native-anchor crosses are off by default, available separately under Show source anchor for alignment investigation; default drawing favours original bitmap artwork rather than covering it with markers. Inspect entities then shows the original generator variant, candidate child type and original activation X/Y ranges, with source-linked browsable frames. There is no new persistent game write: pixel, entity, palette, tile-mask and generator editing/export remain unavailable. Source metadata needed to decode is stored in JS, but no level images, object records or property masks are stored in the editor.

The replacement app/app.js and app/data/stock-maps.js do not bundle source maps or baked tiles. Prior stock-maps.js had 21 base64 maps and app/assets/tiles/ contained source-derived but cached PNGs; those are no longer used. No game map/tile/collectible artwork is visible before original Disk.1 is opened. Once loaded, the 21 native maps, sixteen RLE scenery graphics banks, original palette and 289 masked sprite frames/16-byte directories are all generated in memory from that exact disk. app/assets/sprites/ was P12 output and is obsolete; delete both cached asset folders and app/nzs-sprite-data.js after replacing files. The wiki/images/ PNGs are evidence-only, not game content. The app remains usable from file:// because no external fetch is used to get graphics.
The original disk sprite source is $A099A, decoded to $17000 bytes using $95 RLE; the native directory begins $B42CF. The browser displays all 289 images by default, includes extended collectible $1F IDs $B0..$C9 and letter bonuses $CA..$CF, and explicitly separates type $05 early image references from other animated frames. The map overlay displays original sprite art for known direct source families instead of obscuring it with circular markers; unidentified sources still show markers; generators can additionally show source-linked provisional child artwork. The available representative poses are not verified as the exact runtime frame for every placed object.
Image $BD may be previewed anywhere on 1-1 using Preview on 1-1 in the browser followed by a map click. This is a ghost overlay only and never appears in the exported Disk.1. Its source list addition, behaviour, variant and any extra actor slot use have NOT been proved; packed native record modification remains locked. Do not describe a preview as an in-game collectible test. To make a real new pickup requires a safe relocation and Amiga acceptance path.
Exports: complete Disk.1 export remains exactly the imported image with only changed 4096-byte map slices overlaid. Identical maps mean byte-identical whole-disk output. Original sprite source, directory, placements, warp data, player data and all other bytes stay untouched. All additions and sprite graphic writes remain disabled. Proven source decoding alone does not authorise new encoders or overwriting original packed resource data.
After opening an original Disk.1, the right-side original-image selector groups artwork using revised v0.7 owner feedback: Tiki was temporarily mis-set to $001 in P17; P18 restores standing $000 and retains the first-source-script $001, static rescued-kiwi candidate at $D9 ($DA belongs to the rescue sequence), bonus graphics $C9..$CF, a distinct reviewed $03 visual family beginning $A7, and type $05 available as the complete reviewed family $78..$80, plus separate movement $78..$7C, death/debris $7D..$7E and projectile $7F..$80. RAW native script groups still preserve the true original sequence, including type $03's $A6, type $01/$02's $DA, and type $20's $CA. These are deliberately separate concepts; browse the reviewed group for artwork and RAW group for game code evidence.
The left-panel Animated warp artwork toggle is on by default with Original graphics on map. It alternates native $28/$29 images over outgoing ordinary warp source anchors at an editor preview interval of 420 ms. Neither the game's real warp animation speed nor the exact hotspot relative to the trigger is verified. The corresponding circular outgoing markers are hidden only while artwork is visible; turn art off to inspect data markers. Incoming transition markers persist. All artwork and placement coordinates are generated at run time from the selected Disk.1; there is no pre-rendered tile/sprite/level content and no change to the original 12 warp records.
Visual family selection, warp animation and object pose review do not write actor data or modify map bytes. Export remains the same byte-preserving, map-only writer. Use the P17 reviewed source graphic sheet for graphical identification and Game Code and Runtime for original script distinctions.
The only gameplay authoring operation remains whole-disk map-only export. The P14 module app/nzs-animation-catalogue.js expands native $95 script bytes from the selected Disk.1 at verified source addresses and classifies animation image IDs separately from $8000..$804C control words. It does not change anything on disk. The P14 sprite browser uses the resulting first-linear-segment frame IDs, rather than assuming each actor type owns a consecutive numbered image run. Frame grouping does not establish a creature species, a final playable pose, or spawn-generator child.
With a disk opened: enable Inspect entities, click a native record, select any original image from the indexed/filtered gallery, and choose Preview selected frame. This changes only the browser's temporary preview for that specific record; it is keyed to its native stage, ordinal and Disk offset. Restore candidate drops that override; Clear all reviews clears the temporary collection. Export review JSON writes a plain JSON observation log (NOT_GAME_DATA: true) with the original record metadata and selected image index. The JSON is not an importable editor project or a game resource and does not modify the loaded disk or editable map. A selected entity is highlighted at the unshifted source coordinate, and original source artwork is overlaid using its signed native drawing hotspot. The artist/placement and animation phase still need native runtime confirmation.
Original type $1F image table at Disk $874CE gives slot 8 = image $BD, not the previously assumed numeric mapping $B0 + slot. Stock 1-1 has no type $1F placement, and no native item insertion or game export is enabled. The existing Preview on 1-1 action renders the original Disk-derived bitmap as an explicitly temporary visual only. In-game tests require proving placement-to-slot interpretation and the packed-list relocation/replacement gate; a PNG preview is not a playable collectible. Neither the gallery nor the source script reader contains pre-rendered game sprites.
The editor still reads every bitmap, map and actor record from the opened Disk.1, never from compiled-in sprite graphics, baked map tiles or saved gameplay data. In the original-image browser, the following are two different evidence layers:
-
Owner-identified visual family (first frames
$6E/$78/$81; provisional standing/walking/firing/death/projectile subdivisions for type$04): helps navigate the complete original catalogue without implying adjacent sprite IDs must be one species. -
Native bounded script refs for types
$04/$05/$06: actual nonzero frame words, recovered from finite byte-length original script envelopes, including alternative segments beyond the first reset or branch. Branch execution and runtime frame selection are not simulated.
Image $8D: select $08D in the full gallery or the Type $06 secondary object category. The source-backed description now identifies the MOVE.L #$0000838E,$0014(A4) native instruction and its $8C–$8F image stream. Locate 4 related $06 placements on 1-1 opens 1-1 and highlights its four real parent actor records. The original $8D secondary graphic is not automatically placed at their anchor; it is a dynamic effect with an untraced spawn trigger. Optional manual Preview selected frame still does not change the native record or exported disk. Any experimental display of the effect must be explicitly labelled as a preview. The user-confirmed entity marker alignment is unchanged.
Script-derived references are not a general object catalogue. The $1F 17-image lookup is an indexed sequence, not an established record associating every graphic with type, score and effect. $20 has six native letter images and a numeric update path; values, hit effects and parameter mapping must still be recovered from code. $8D is not in either known collectible family.

Safety retained: 289 original images remain available; no embedded images are added by P15, and only the existing 4096-byte map slices can be exported. Entity creation, sprite editing, dynamic-child code, scoring, collectibles and warps remain read-only pending verified encoders and Amiga validation.
The original P12 gallery proved sprite decoding from saved RAM, but its bundled graphics and descriptor table were a temporary development solution. P13 replaces these with live Disk.1 decoding. P12's source-matched RAM renderer and validation evidence are still documented in Wiki 04; its PNGs and JavaScript descriptor cache are not production inputs.
Read-only analysis can now be implemented precisely; mutation remains disabled. The P09 native stage-warp table has 20 × 8-byte logical records, with 12 configured rows. Disk storage is only 108 RLE-packed bytes, directly adjoining original game executable. The game loads one row into a 10-byte active record containing the extra gate/status byte; that extra state is runtime-only, not an editable row property. 4-4b requires its independent special-mode flag, object list and collision table, and is absent from the ordinary 20-row indexing.
Use the existing three-column Indy Heat-style UI. In map navigation, provide independent read-only toggles for Warp out (amber), Warp in (cyan, approximate pixel-origin until tested), normal entry $00, objective $01/$02, header fields, $03 generators and direct actors. Never combine all entry/exit-like controls into yellow points or label an empty table row “no warps” without the qualifier in this specific transition table. An editor popup/tooltip for each native transition should show source/destination stage, source tile coords, raw destination X/Y and the original row ID; the main screen should not contain developer explanation text.
| Operation | P09 status | Native constraint |
|---|---|---|
| Display 12 confirmed table transitions | Research-supported | Use decoded 160 bytes and nonzero record tests |
| Display eight empty rows | Research-supported | Must show as unconfigured, not absent from entire game |
| Change source tile coordinate in an existing row | Do not export yet | Verify trigger and coordinate convention on Amiga; preserve compressed source bytes |
| Change destination stage / raw X,Y in same row | Do not export yet | Validate new arrival, player-safe position, adjacent callbacks and source re-encoding |
| Enable an empty row as a new warp | Unsafe today | RLE packed data would grow into RAM-loader executable; require relocation/expansion strategy |
| Add two or more warps to one stage | Unsupported by this table | Additional generator or custom table/routine required; cannot just append to 20 × 8 rows |
| Change 4-4b transition after kiwi rescue | Unsafe today | Must trace rescue callback -> special loader and native arrival, not the ordinary 4-4 record |
| Change goal/start based on assumed warp | Not supported | Separate native records and callbacks; no interchangeability |
Option A — same-length repack: for records already populated, preserve 108 compressed bytes exactly; change non-escape literal fields only when every affected source byte is known, no $95 collision occurs, and original compressed size is unchanged. This is potentially suitable for a minimal native test but not a broadly safe final authoring method.
Option B — relocate packed source inside Disk.1: requires all loader references and resource boundaries, a matching native RLE writer, enough original disk free space, relocation/fix-up of code and pointers, and exact WHDLoad sector-loading preservation. Merely extending the table at $84B14 corrupts executable.
Option C — runtime sidecar: WHDLoad loader loads a new table to stable RAM and redirects both stage-row selection and active-record setup; requires verified memory allocation, all relevant code references and special 4-4b handling. A larger/custom table would also need modified stage-row addressing, and possibly per-stage multiple transitions. This is the favoured future architecture to test, not a working feature.
Proof of safe export: unchanged disk byte identity; altered source produces exactly expected decoded table; real runtime test of 1-1 -> 1-4 and one same-level transition; no corrupted graphics/menu/boss events; special 4-4 rescued-kiwi path still functions; map and entity data otherwise untouched.
P08 did not change the HTML5 application. The following should inform its future implementation:
Modes and layout: maintain the Indy Heat arrangement: top file bar, left stage/map/overlay navigation, centre large canvas, right compact tile and future object-edit tools. Technical provenance and limitations belong in tooltips/Wiki rather than visible paragraphs. Each distinct overlay has its own toggle: normal $00 first record, $01/$02 goal, header +$0E/+10 raw field, type $03 generator, direct actor types $04..$2D, and—only after actual native source discovery—real warp entrances and arrivals. Do not reuse one yellow-marker layer to describe all these different sources.
| Authoring operation | P08-approved action | Required gate before writing |
|---|---|---|
| Read native actor records and show raw type/parameter at x,y | Yes, read-only overlay can be implemented | Preserve source disk offset and original record order. |
| Move/change a 4-byte actor record in place | Not yet allowed | User runtime acceptance for each type/parameter, including start/goal and generator. |
| Add/delete an actor or generator | Not yet allowed | Repack+relocation proof, complete reference patching, capacity guard and native test. |
| Change generator scripts | Not yet allowed | Full actor script parameter and descriptor source encoding; 32 + 5 distinct slot limits. |
| Edit 4-4b actors or warps | Not yet allowed | Special flag/callback source understanding, hardcoded $DA3A updates and proof of player transition. |
| Graphics palette/tile native edit | Not yet allowed | Verified repacker (unchanged bank bytes match) and proven size/loader bounds. |
| Fixed 64×64 map tile cells | Existing P03 map-only workflow | Continue outputting exact-size Disk.1 and preserving everything else. |
Practical extension strategy (proposal, not implemented): prefer a runtime sidecar/custom arena over expanding the original packed object block in place. A WHDLoad loader or other verified startup hook could allocate a new stable RAM area, install extended per-level placement lists there, update the 20 normal stage catalogue pointers, and separately redirect the two hardcoded $DA3A 4-4b uses. If native tile classifications move, update the special $CFC2 consumer too. This approach needs a real memory map, a callback-stable allocation lifetime, an exact relocation/fix-up process, and original-game WHDLoad tests; it does not yet have acceptance evidence. Alternative full-disk repacking would need to rewrite the original encoded source stream and sector/load metadata, a larger and less local change. The intended user workflow can keep the normal editable .Disk.1 as the baseline and optionally supply sidecar resource files once the slave's loader is proven.
What a future editor should guard: preserve original record ordering and first $00 entry; raw type byte maximum only within native verified cases; $03 variant indices $00..$11 in stock, no generic type/script writer; 32 door slots and distinct five-child slot allocation must be displayed as separate capacity diagnostics; preserve 4-4b's special linkage. Do not enable add/delete simply because a new list fits in an HTML array.
Safety principle: byte-preserving editing, no forced relocation unless every consumer is traced; checksum and allocator behavior must be tested on owner's actual WHDLoad environment. Exporting a syntactically valid Disk.1 is not proof of working runtime game data. Use source-backed original actor graphics rather than distorted bitplane-guess sheets for the eventual sprite editor.
See visuals_P08/06_edit_capacity_and_relocation.png and the source-specific proof in the Disk/Entities/Code Wiki pages.
Type $03 native door/generator lists and their script descriptors are read-only research inputs in this pass. No edit/export has been added to the P03 browser app. The game allocates at most 32 door slots per stage, and the descriptor stream contains source-to-RAM fix-ups not yet reconstructed for writing. Preserve the existing P03 map-only, byte-preserving Disk.1 export contract. Entity displays must not overlay invented warp markers or mark zero header coordinate pairs as locations. Future UI uses top load/export, left navigation/overlays, central edit canvas, right palette/properties, tooltips rather than explanatory panels.
Research-only pass. The live HTML5 application has not changed from P03. Future app modes should follow the established three-column Indy Heat-inspired layout: top bar for disk loading, import/export and history; left for level navigation and visibility, centre for the tile-accurate map, right for tools/tiles/objects. Interface text must be minimal, with concise tooltips instead of explanatory panels. New source-derived actor overlays should be read-only until the 68000 handler, type ID and list-size/export constraints are proven. Do not silently label arbitrary $03 records as enemies, and do not change unrelated map bytes during export.
The research manifest research/entity_manifest_disk.json now provides true 21-map object overlays: $00 = candidate normal start (once/map), $01 = candidate ordinary exit (16 maps), $02 = candidate boss objective (5 maps), $03 and other IDs = unknown; header +$0E/+10 must remain an independently toggled annotation. Always retain a clear way to distinguish confidence tiers in visuals.
P02 — 12 October 2026. Three-column editor with Disk.1-native graphics previews/decoder.
-
Load: 901,120-byte disk with
DOSsignature, 21 raw map slices, 16 native graphics banks decoded from on-disk RLE into 16×16 four-bitplane tiles. See Maps and Tiles. Any unexpected graphics header/length rejects the load without partial state mutation. - Before load: empty map and disabled editing/export. No cached map or tile atlas is supplied; the user must open Disk.1.
- Edit: map tile IDs 0..255; 64×64 cell map, y=0 in storage at bottom. Unknown/out-of-bank references display diagnostic hatches but retain the original byte. Undo/Redo is per level.
- Export map: exactly 4,096 bytes in original bottom-up byte order.
- Export Disk.1: exact copy of imported image with changed map slices replaced; no other bytes modified. If the user changes nothing, output is byte-identical.
-
Map offsets:
3_4is$46280(not the wrong P01$4BA80);5_3remains$79080, but now displays bank 14 from native disk RLE rather than misnumbered reference art. - Export graphics: deliberately not available. Native compressed tile bank editing/repacking remains pending 68000 compatibility verification. Sprite, enemy, player start, exits, warp and collision editing are not yet supported.
Developer tests: node tests/test-core.js /path/to/Disk.1 verifies 21 maps, 16 graphics bank decompressions and exact native tile-pixel hashes, plus unchanged/single-cell Disk.1 export invariants. Live WHDLoad acceptance is still required for edited games. UI favours short labels/tooltips and does not place binary offsets or debug text in the ordinary control panels.
Level bounds (checked by default): dim rows outside each header's declared map height (without deleting or locking the underlying 64×64 map). Header point (off by default): show a yellow read-only question marker at the unclassified header coordinates. Both switches are display-only; neither creates/edits monsters, player positions or warp links. Palette swatches are decoded from bank metadata. Header words, sprites, inter-map records and compressed graphic resources are never written to Disk.1.
Do not enable writes for the new candidate pickup classes $1F/$20 just because they have been located. The fourth byte of $20 is stock-limited to $00–$05, and its native handler manipulates bits of global gameplay state; arbitrary parameter changes may break collection logic. Type $1F uses at least seven parameter values, including $40-flagged variants. Both reference native animation/control word streams rather than proven raw bitmap pointers. Sprite bitmap dimensions, mask/planes and source bank placement must be derived from the game renderer before importing editable art.
Potential future safe milestones: (1) source-backed read-only placed-object and generator palette, (2) same-count, same-size coordinate changes only, independently validated in native gameplay, (3) encoded variable-size list relocation with all stage and special 4-4b references adjusted, (4) independently verified animation- and bitmap-resource repack, (5) load-time sidecar support if WHDLoad memory/lifetime contracts allow it. The 32-generator and five generated-child-slot constraints remain as previously documented; type $20 and $1F are not guaranteed to use those same pools.
The updated app/index.html includes the new nzs-entities.js view-only object overlay and right-hand inspector. The original app.js, nzs-core.js, nzs-graphics.js, nzs-level-headers.js, maps and tile assets are unchanged: the existing 901,120-byte map-only export remains the only permitted Disk.1 writer. The entity decoder reads original placement records from documented START[i]+2+j*4 and loads native ordinary warps by decompressing exactly 108 physical bytes [0x84B14,0x84B80) to 160 logical bytes; it never writes them back. An editor may show source and −16 px candidate Y positions side-by-side, but the stock coordinates stay immutable. All image/state controls for unproved actors, generators, warps, sprites and palettes remain disabled.
To install: copy app/index.html and app/nzs-entities.js from the ZIP into the existing P03 app/. Do not delete other P03 files. Keep both pages complete. Test via node tests/test-entities-p11.js /path/to/Disk.1; this uses only Node's standard library. Open the disk through the usual toolbar after loading the page to populate read-only actor data. Choose Inspect entities to suspend painting while clicking overlays; choose it again to return to painting. The viewer is not a binary editor for actor scripts.
Unproved items: native frame index to pixel-data lookup, genuine sprite sizes/palettes/masks/hotspots, object +$1F/$20 identity and exact contact effects. The coordinates compared in wiki/images/p11_native_backdrop_anchor_*.png are visual experiments only, not native code confirmation. Do not promote the −16px setting to a permanent correction without an Amiga rendering trace.
The new drop-in module app/nzs-world-navigation.js groups P03's existing #levels rows into native HTML <details>/<summary> elements. Only one World is normally expanded; summaries are keyboard operable and show the number of maps (including special 4-4b). The five labels are World 1 - Auckland, World 2 - Rotorua, World 3 - Waitomo Caves, World 4 - Strait Cook, World 5 - Mt. Cook. Names are UI metadata, not a change to any stage number or disk address. It keeps the three-column toolbar/left/navigation/canvas/right inspector arrangement and avoids any modification of the production P03 app.js.
Read-only app/nzs-entities.js now anchors direct actors and type $03 generator placement points to the native source-code conversion Xtile×16+4, Ytile×16, with stage-height adjustment for the full 64×64 canvas. Separate dropdowns for X and Y each offer −16, 0, +16 pixels, default zero. The Show source anchor checkbox draws an independent white cross at the exact decoded point while preview adjustment shows a separate colour marker. Offsets affect only display projections of native actor placements, never the underlying four-byte {type,x,y,parameter} fields, the MAP writer, objective stage indexing, compressed warp data or sprite source blocks. Original bitmap hotspot alignment is not yet proven: do not treat one of the nine candidate marker positions as a confirmed gameplay sprite location.
Regression: Node module checks include all five canonical World labels and 21 level mappings, immutable 599-record/12-transition source parsing and ±16px X/Y projection; Python independently checks exact 14-byte native-coordinate instructions at both loader addresses in the original disk and hash-verified Stage 1_1.uss. No native writes beyond P03's map-only export are introduced. Browser UI is intended for additional owner visual acceptance; passing the decoder and metadata tests is not proof of actual rendered BOB sprite alignment.
