01 disk and binary layout - HoraceAndTheSpider/New-Zealand-Story-Editor GitHub Wiki

P09 β€” Separate compressed native transition table, with code immediately afterwards

Original Disk.1 SHA-256: fec7ce66934497b65745aa658599bdc697cf0ea0111d77d211fce3f48e27b416. Savestate SHA-256: 4656b4af4322ce946cd8cf0decf843ffb5a8cf7e80fbf153df5c0a2fe317cadb.

Newly verified: a stock 20 Γ— 8 = 160-byte per-stage transition table exists at loaded RAM $04B02..$04BA1, but it is stored in Disk.1 at $84B14..$84B7F as 108 bytes using $95 escape-RLE. It is followed immediately by executable bytes at Disk $84B80. The loaded executable starts at RAM $04BA2. The $95 run grammar used in this particular source range is 95 <value> <count-minus-one>. Four zero runs of lengths 8, 16, 16 and 24 account for the 52-byte saving. The reconstructed bytes match all 160 RAM bytes. This is a reproducible source format for reading; a general-purpose safe writer is not yet approved.

The preceding active transition record at RAM $04AF8..$04B01 comes from separate source bytes at Disk $84B0A..$84B13 and is also dynamically overwritten during stage setup; it is not the table's first stage row. The stage selector at RAM $0422E and transition activation/commit functions are documented in Code and Runtime.

Editing hazard (high): direct in-place edits to an already populated table row may be representable as same-size disk changes if the byte stream and its escape boundaries remain invariant; editing an all-zero row to add an entirely new transition would ordinarily expand the 108-byte compressed source and collide with adjacent executable. Any repacking also needs source loader/stream-length boundaries, the correct escape encoder, and user Amiga testing. Do not expose a variable-size transition-table export in the HTML5 editor at this stage. See the App Editing and Export gate.


P08 β€” Source patching and relocation constraints (13 October 2026)

Status: byte-verified against the supplied 901,120-byte Disk.1 (SHA-256 fec7ce66934497b65745aa658599bdc697cf0ea0111d77d211fce3f48e27b416) and 512 KiB Chip RAM recovered from Stage 1_1.uss. Full assertions and records: research/P08_research_and_visuals.py, P08_verified_findings.json.

The 21 object lists are packed with no free bytes between them. The original source region is $8CFE4..$8D992 inclusive, 2,479 bytes. These account for exactly 599 Γ— 4-byte native records (2,396 bytes), 21 Γ— 2-byte list prefaces (42 bytes), 20 Γ— 2-byte terminations and the last list's single $FF termination (41 bytes). In the original physical ordering, each list's end equals the next list's beginning, including the extra 4-4b list. Disk byte $8D993 is $95, not padding. This verifies that a casual append to a level will overwrite subsequent records or adjacent loader data. The leading per-list preface is not proven to be a count or storage-capacity field.

4-4b has two hardcoded RAM-data references outside the normal 20-entry stage table. Native instructions at RAM $04224 and $0AE74 explicitly load RAM $0DA3A when special-mode flag +$26(A6) is set. This corresponds to 4-4b's source list at disk $8D78C, verified against RAM. The 20 ordinary catalogue pointers remain at disk $85DB7, but updating those 20 entries alone will not redirect this special list. A third native branch at RAM $0C7E6 selects alternate map classification RAM $0CFC2.

Additional special-area table constraint: 4-4 has a 20-word tile classification array at RAM $CF98, terminated at $CFC0; 4-4b has 56 words at RAM $CFC2, terminated at $D032. The special table source diverges from RAM after 54 bytes near disk $8CD71 (including $95 encoding). It cannot be expanded or exported as a simple file-offset write. See the Maps and Tiles page.

Binary editing tiers:

Operation Supported by current knowledge Why
Fixed-size tile map cells Yes: existing map-only export, subject to runtime gameplay test Changes a known byte in a fixed $1000 map without changing addresses.
Existing placement record: same byte count Structurally possible; editor writes still disabled Record positions/format verified, but type-specific flags, game validation and semantic constraints are incomplete.
Insert/delete records within a list Not yet safe Shifts all subsequent packed lists and pointers; changes terminator and likely disk loader obligations.
Relocate entire object-list block Not yet safe Requires RAM/source loader-patch contract, normal 20-entry pointers, two extra 4-4b literal references and any unknown consumers.
Add generator IDs/variants Not yet safe 32 slots, 19 descriptor-table indices (only 0–17 used in stock), 5 child-actor slots and script parsing constraints.
Grow compressed tile graphics or sprite banks Not yet safe Original bank length/destination allocation/repointing and any source fix-ups not proved.

Important source vs RAM distinction: the runtime actor-dispatch table begins at RAM $058D2 and consists of 12-byte entries for the 46 ID-indexed rows covering the observed stock range $00..$2D; its source area near disk $8589A is not a direct byte copy. For example, RAM begins 00 00 93 1E 00 00 AF 5C 00 00 00 00, while those disk bytes start 00 02 93 1E 00 00 AF 5C 95 00 05 AE. This is consistent with loader expansion/fix-ups but does not yet define an editable source encoding. Never use a RAM pointer/address as a direct Disk.1 write offset in this region.

Preferred future investigation path (not implementation): a WHDLoad-side runtime arena for expanded source-derived records may avoid resizing adjacent disk object lists, but requires loading custom sidecar bytes, patching 20 catalogue RAM pointers plus 4-4b literal references, and ensuring the allocated area does not conflict with blitter/chip buffers, later stage reloads or engine globals. Repacks directly inside Disk.1 instead require understanding its $95 source encoding, module/sector reader and every affected pointer. Neither path is currently confirmed safe.

Relocation investigation must first establish loader bookkeeping, repointed absolute operands, region sizes in RAM, save-state differences, live WHDLoad acceptance and a reversible export test. Preserve unrelated bytes. This does not authorise inserting game-object records today.


P06 β€” confirmed native placement reader

Direct native code evidence (RAM $04216 / Disk $84230, and reader RAM $05B52..$05C8D / Disk $85AC9..$85C04) verifies the 20-stage selector's pointer +$04 selects the list, the prefaced first record supplies special entry coordinates, $FF ends the subsequent type-dispatched records, and type $03 uses its fourth byte as a native 19-way descriptor index. Source matching and disassembly are documented in Game Code, full stage counts and role cautions in Entities.


P05 β€” Original runtime stage catalogue and native placement stream (12 October 2026)

Major source-verified result. The 20-entry game-stage catalogue is present verbatim in Disk.1 at $85DB7..$85EF6 and in the supplied Stage 1_1.uss Chip RAM at $05E40..$05F7F (20 records Γ— 16 bytes). Both ranges match all 320 bytes, not merely selected signatures. This is not the sequence of map headers at $18C00, etc.; it is a separate runtime configuration catalogue.

Each big-endian 16-byte stage entry reads:

Record bytes Observed contents Example 1-1 Status
+$00..+$03 RAM pointer to packed nibble-classification table for tiles $0000CBA4 Table content and consuming native loop verified; class meanings still unknown
+$04..+$07 RAM pointer to stage's object-placement block $0000D292 Verified against disk and terminated record stream
+$08..+$0B RAM pointer to four-byte ASCII level identifier/label $0000CBA0 Labels such as 1_1, 1_2 are visible before classification tables
+$0C..+$0D Unclassified big-endian word $0002 Unknown
+$0E..+$0F Unclassified big-endian word $0012 Unknown

For the 20 canonical game-stage selectors, the order is 1_1..1_4, 2_1..2_4, 3_1..3_4, 4_1..4_4, 5_1..5_4. The additional map 4_4b is not a 21st catalogue entry. Its own distinct, valid-looking placement data nevertheless occupies the gap $8D78C..$8D807 between 4-4's block and 5-1's block. It is likely an alternate area, but the code that selects this extra list remains to be found. Do not shift the 5-1..5-4 table mapping to insert a fake 21st pointer.

Native placement data, including the alternate 4-4b block, occupies Disk.1 $8CFE4..$8D992 (inclusive), with 599 complete 4-byte entries. The 20 normal pointers in the stage catalogue are RAM-space pointers; for this continuous region disk_file_offset = RAM_pointer + $7FD52. This relationship was verified against the entire copied block, not assumed from one entry. The final 5-4 terminator is a single $FF byte at $8D992, followed immediately by unrelated $95... source bytes. In saved RAM it is followed by $00; a decoder must not consume the following disk byte as a mandatory terminator pad.

The stage catalogue's first placement pointer corresponds to Disk.1 $8CFE4 / RAM $D292. The next stage begins at $8D01C; all blocks are concatenated and each is closed by an $FF record-type sentinel (other stages have a $00 padding byte). The exact per-stage file offsets, lengths, list lengths and object entries are supplied in the complete research/entity_manifest_disk.json; the human-readable summary is on Game Objects and Entities.

The previous P03/P04 statement that dynamic spawn/placement data had not been located is superseded. What remains unproven is the actor-type mapping, event timing/activation, object AI behaviour, and warp transfer logic. The original code and its pointers have now been located, making these tractable follow-on investigations.

P05 source-to-snapshot executable matches

A byte-for-byte scan also directly linked key pieces of executable code in the captured RAM back to original disk offsets:

RAM first byte Disk.1 first byte Match Function/evidence
$04172 $8418C at least 64 bytes references level header RAM $44AA6
$04628 $84642 at least 64 bytes another header reference
$0BE5A $8BDBA at least 100 bytes LEA $00044B26,A0 (map) at RAM $0BE5C
$0C7D4 $8C6A1 at least 300 bytes reads 1-1 header width/height and selects table pointers
$0C83C $8C709 at least 130 bytes reads map, expands tile-classification words to 2Γ—2 cells
$05E40 $85DB7 exact 320 bytes stage metadata table
$0D292 $8CFE4 exact through $0DC3F native entity list sequence (with noted final terminator difference)

Do not apply a universal RAM→disk shift to the entire game program; independent ranges have different offsets. The table and placement-pointer relocation values above apply only where verified by matching source bytes. Read Game Code and Runtime for code evidence.


Disk and Binary Layout

P02 β€” 12 October 2026. Baseline Disk.1 is 901,120 bytes (1,760Γ—512 byte sectors), SHA-256 fec7ce66934497b65745aa658599bdc697cf0ea0111d77d211fce3f48e27b416.

The image begins 44 4F 53 00 (DOS\0). This does not establish an ordinary AmigaDOS filesystem: the game stores raw map and compressed graphics data at fixed observed offsets. The bootloader, the retail 68000 readers and WHDLoad slave still require disassembly. Do not run AmigaDOS filesystem assumptions against the map data.

Proven static data envelopes

  • 21 level maps, each $1000 byte: exact offsets and bottom-up coordinates in Maps and Tiles.
  • 16 compressed indexed-tile graphics banks: header offsets and lossless RLE/planar decoding in Maps and Tiles. These constitute a verified disk-to-pixel extraction, with each decoded bank containing a $80 byte preamble (signature, palette words and further metadata) plus $80 bytes per native tile.
  • Many neighbouring map starts differ by $1600. Of the $600 bytes between map grids, the last $80 are now verified to be the following level header; the preceding $580 remain unclassified.
  • The AMOS source incorrectly sets 3_4 map offset to $4BA80; the coherent location is $46280. This is a correction to static layout not yet traced to an original 68000 instruction.

UAE state used as independent byte-level evidence

The supplied Stage 1_1.uss begins with ASF , with CPU , DSK0, CHIP, CRAM chunks. DSK0 references an IPF filename, not necessarily an identical disk copy. The CRAM chunk at file offset $0980 contains 512 KiB of chip RAM (data start $098C). At RAM offset $3CB26 (relative to CRAM payload), consecutive $80-byte records match the indexed 1_1 tile graphics from the native decoder byte-for-byte across the confirmed source run. This independent RAM evidence supports the 4-bitplane row-interleaved model; it does not prove all 68000 RAM mappings are the same between IPF and WHDLoad.

Write boundaries

Full-disk export starts from the exact loaded image, updates only explicit map slices and retains its original size and all other bytes. Graphic banks are currently read-only. Repacking them requires a proven encoder and live game test, not merely correct rendering. No original Disk.1 bytes are bundled in the editor ZIP other than extracted 21 map records and derived graphics preview PNGs.

P03 β€” level header discovered and 68000 inspection starting points

Every one of the 21 maps has a $80-byte record directly before its $1000-byte tile grid, at mapOffset - $80. The two-byte ASCII signature is 30 31 ("01"), followed by two big-endian 16-bit dimensions (+$02, +$04). The dimensions read 64Γ—14, 64Γ—32, 64Γ—48 or 64Γ—64. The first 21 headers all satisfy this structural pattern; the corresponding map bytes fit within the image. See the full table in Maps and Tiles.

Within the common $1600 level spacing, the formerly unidentified $600 after a map includes $580 between the preceding map end and the following level's $80 header. This $580 region is 11Γ—$80 bytes long and often repeats nearly identically across adjacent levels; it is not evidence of 1,536 bytes of independent enemy/warp records. Its meaning remains unknown: neither sprite data nor collision data has been verified there.

The broad Disk.1 range $07C000..$08C000 contains many 68000-like opcode signatures; later disk regions also contain game-associated strings including KIWI POS: near $CD81E. This identifies investigation targets only, not trusted runtime code entry points or entity tables. Precise code base addresses and Disk.1 β†’ RAM mappings remain to be established.

P04 β€” independently verified level-copy location in the supplied UAE save state

Evidence: supplied Disk.1 (SHA-256 fec7ce66934497b65745aa658599bdc697cf0ea0111d77d211fce3f48e27b416), supplied Stage 1_1.uss (SHA-256 4656b4af4322ce946cd8cf0decf843ffb5a8cf7e80fbf153df5c0a2fe317cadb). This is a comparison of bytes, not an inferred mapping or a report from gameplay. The UAE CRAM block starts at savestate file $0980, followed by a 12-byte chunk header; the $80000-byte Chip RAM snapshot starts at savestate file $098C. Therefore RAM address A appears at save-state file offset $098C + A.

The whole $1600 (5,632-byte) 1_1 header/map/trailer area is identical between the game disk and the saved memory:

Area Disk.1 physical offset Chip RAM address in this snapshot Length Result
Level 1_1 header $18C00 $44AA6 $0080 Byte-identical
Tile map $18C80 $44B26 $1000 Byte-identical
Unclassified trailing data $19C80 $45B26 $0580 Byte-identical
Whole level-copy block $18C00 $44AA6 $1600 All 5,632 bytes match

The first mismatch is at RAM $460A6 / disk $1A200, where the disk holds the next level's header but the live game snapshot holds unrelated data. This proves a contiguous one-level RAM buffer for the captured 1_1 scenario, rather than the unsupported claim that all 21 headers/maps are simultaneously resident there.

This mapping is specific to the user's provided snapshot and is not a general disk→RAM offset for arbitrary sources. RAM pointers are not automatically file offsets. See the 07_level_1_1_disk_to_ram.png evidence graphic supplied alongside the P04 handover.


P10 β€” Actor animations and editing capacity additions (13 October 2026)

P10 recovered ten additional byte-matched source Disk ↔ saved RAM anchors for live actor behaviour and animation/control streams. These are not located by assuming a constant RAM-to-Disk delta; each was found by exact contiguous matching. Examples: $075A6 RAM ↔ $87518 Disk (type $20 animation stream), $075D8 RAM ↔ $8754A Disk (same handler), $0767A RAM ↔ $875EC Disk (type $1F handler), $080D8 ↔ $8804E Disk (type $04 stream). See research/P10_evidence_report.json for all anchor lengths and original bytes.

Why these addresses are not an editing recipe: stage placement lists $8CFE4–$8D992 are tightly packed; adding/erasing one actor can overwrite the next list, and additional 4-4b references would require coordinated changes. Live actor-table pointer values at RAM $058D2 differ from disk source values (load-time pointer transformation); simply inserting 12-byte actor descriptors or lengthening an animation stream overwrites subsequent code/data. There is as yet no tested disk relocation, no source-size budget for arbitrary sprite bitmaps, and no accepted global actor density increase. Treat editor direct-actor and image resource controls as read-only until code-safe source mapping and relocation are established. The unchanged map-only export contract remains authoritative.

⚠️ **GitHub.com Fallback** ⚠️