Changelog

All notable changes to TAKEOVER are recorded here. Format is informal:
release version, date, then a flat list of fixes and additions.

v2.0.1 (2026-05-18): Enum rename pass; T5 baseline re-capture

Maintenance release. No engine behaviour change vs v2.0.0; T1 cell
buffer parity is byte-identical to v2.0.0 across all 5 production
scenarios with row 24 masked. T5 event-trace baselines move forward
to a clean naming scheme.

Changed
- Event-kind names cleaned up. The Phase 6 V-suffix variants
  (TKE_TEXT_BEGIN_V2, TKE_TEXT_END_V2, TKE_REWRITE_TAG_V2,
  TKE_CLEAR_SCREEN_V2, TKE_CLEAR_REGION_V2, TKE_PAGE_V2) now use
  the base names. The original Phase 1 reserved stubs of the same
  base names (never emitted) were removed. TKE_DELAY_FORCED_RETIRED
  (the Phase 7 S-3 placeholder kept to preserve enum numeric values)
  was deleted outright. Net result: every event kind on the wire is
  spelled cleanly and the enum has 7 fewer dead slots.
- T5 baselines re-captured. The numeric event-kind values shift
  with the slot deletion, so pre-v2.0.1 event traces (which compare
  numeric kind bytes implicitly via line-text) only match v2.0.1
  binaries after the rename pass. Fresh baselines land at
  tests/expected/<scenario>_events_v2.0.1.txt for all 5 production
  scenarios; the v2.0.0 baselines stay on disk as
  <scenario>_events_v2.0.0.txt for historical reference.
- Menu footer version string. Bumped from v2.0.0 to v2.0.1.

Verified
- T1 cell-buffer parity byte-identical vs tests/golden/*.cells with
  row 24 masked for all 5 production scenarios.
- All 115 unit tests across --unit-tests, --phase3-tests,
  --phase4-tests, --phase5-tests, --phase6-tests modes pass.
- wmake phase6-gate (static analysis + DGROUP zero-shell + keyword
  parity + normalize-far + tag-write allowlist + themes-segment
  audits) green.
- 0 shell-side DGROUP near-data across all 22 shell translation
  units (Cerberus discipline preserved).

Closes GitHub issue #1.

v2.0 (2026-05-18): Engine/shell split, scrollback, theming, card menu

The 13-phase v2.0 rework. v1.x was a single-binary scenario engine
with rendering, audio, input, and the scenario state machine all
living in one ~7500-line engine.c. v2.0 is the same engine
restructured into an event-emitting core plus a shell-resident
consumer. User-visible features new in v2.0: a scrollback overlay
(PgUp), per-AI theming (each scenario has its own colour palette), a
card-gallery menu replacing the v1 dropdown list, a live status bar
with rotating context hints, a context-sensitive F1 help overlay, and
a [meta] header for scenario authorship metadata. All 5 v1.x
scenarios run unchanged on v2.0; v1.x saves migrate to v3 silently on
next save.

Architecture
- Engine/shell split. The engine is now a pure scenario state
  machine emitting events on a fixed-size ring; the shell consumes
  events and owns all rendering, audio, input, and screen-effect
  surfaces. The split is invisible to scenarios (the .scn format is
  unchanged) but gives v2.1+ headroom for new shell surfaces (a web
  replay viewer is sketched in the design doc as a v2.1 candidate;
  nothing builds on it yet).
- Theming. Six themes ship: MENU plus one per AI (AXIOM, HUSHLINE,
  KESTREL9, ORCHARD, CINDER). Themes are filename-inferred for v1
  scenarios; v2 scenarios can override via [meta] theme:. Themes
  carry body/highlight/dim/status attribute bytes plus typing speed
  (cps), paragraph pause, transition kind, climax kind, and stinger
  id. Each AI has its own visual personality without scenario authors
  writing colour bytes by hand.
- Parser ceiling lift. v1's 32-command-per-state limit (cmd_t
  commands[32] inline per state) is gone; v2 uses a shared
  4096-command pool via _fmalloc. The 5 production scenarios were
  all pressing the v1 ceiling; v2 has headroom.
- DAT v3 format. The save file (TAKEOVER.DAT) bumps to v3 with
  XOR bitrot guard, achievement bitfield (24 bits over 3 bytes),
  per-ending bit semantics, reading-speed enum persistence, and
  cumulative playtime in seconds. v1 and v2 saves migrate to v3
  silently on next save.

Added
- Scrollback overlay (PgUp). Captures auto-scrolled lines and
  page snapshots in a 200-row ring (32 KB cells + 1 KB index) via
  _fmalloc. PgUp opens the overlay; Up/Down/PgUp/PgDn/Home/End
  navigate; Esc closes. Available from every shell state (in-scenario
  delay, choice menu, input prompt).
- Context-sensitive F1. The help overlay now adapts to the
  current shell state. Six panels: IDLE, DELAY, FLASH, CHOICE, INPUT,
  OVERLAY. Each panel lists the keys active in that state. v1's F1
  was a single static panel.
- Card-gallery menu. The character selection screen now shows
  each AI as a card with ASCII portrait, name, role, and description.
  Settings, About, Cracktro sub-menus replace v1's single-screen
  design. Completion markers below each card show which endings have
  been seen. F8 replays the hidden cracktro from v1.1.
- Live status bar (row 23). Rotating context hints visible in
  every shell state. Theme-aware; refreshes on TKE_THEME_CHANGED.
- Per-AI theming. Each scenario has its own colour palette
  (Axiom in bright clinical white, Hushline in muted greys, Kestrel-9
  in alert red, Orchard in warm friendly tones, Cinder in a deeper
  meta-palette). Status bar, menu highlight, choice cursor, and
  reading-area body text all follow the active theme.
- [meta] header in .scn files. New scenarios can declare
  version, theme, title, author, year, content warnings. v1 scenarios
  with no [meta] block continue to load (default to version: 1, theme
  inferred from filename).
- narrate: composite verb. Combines attr + text + delay in one
  line; reduces scenario-file boilerplate. Available in [meta]
  version: 2 scenarios.
- page verb. Snapshots the reading area into scrollback and
  clears for a new page; available in [meta] version: 2 scenarios.
- theme: verb. Mid-scenario theme override; available in
  [meta] version: 2 scenarios.
- news_live: verb (placeholder). Requests live news from the
  NetISA INT 63h vector; falls through to the fallback string if the
  TSR is not loaded. NetISA's own Phase 3 will wire the real fetch;
  v2.0 ships the fallback path for every scenario.
- Achievement system. 24-bit bitfield in TAKEOVER.DAT v3;
  per-ending bits per AI; About menu shows progress copy from a
  24-entry copy table.
- Cumulative playtime tracking. TAKEOVER.DAT v3 records total
  seconds played across all runs; surfaced in the About sub-menu.

Fixed
- DGROUP near-data footprint. v1.2.1's static buffers and tag
  table lived in DGROUP; v2 moves them to per-TU FAR_DATA segments.
  DGROUP shrunk from 63 KB (v1.2.1) to roughly 15 KB (v2). Working-
  set memory is similar; the reorganization gives v2.1+ headroom for
  new features.
- 8088 stack discipline. Long render paths previously consumed
  deep stacks via recursive helpers; v2's event-loop shell uses
  iterative dispatch with a maximum recursion depth of 2 (overlay
  nesting). No measured stack-overflow risk on real iron.
- Audio keep-alive during long waits. The OPL2 tick now pumps
  every 1024 cells during scrollback eviction (~17 ms on 8088),
  preventing the audible dropout v1.x had on text-heavy transitions.
- F1 help works during typewriter narration. v1.2.1's F1 only
  opened at prompts; v2's F1 dispatches from every state including
  mid-delay and mid-flash.
- Tag rewrite cell_count semantics. v1.x had ad-hoc cell-count
  rounding for tag rewrites; v2 enforces pad-on-shorter and truncate-
  on-longer with a stale-tag no-op.
- shell_poll_keys peek-then-consume. v1.x's input loop drained
  the keyboard buffer on every poll and lost any non-hotkey char.
  v2's peek-then-consume preserves typed characters for the next
  read_input call. Caught by Phase 8.1 iron-test on 320CDT; cell-
  buffer harness missed it because scripted input bypasses the
  keyboard buffer.

Compatibility
- v1.x scenarios run unchanged. No .scn edit needed. The
  filename-inferred theme lookup gives v1 scenarios their per-AI
  colours automatically.
- v1.x saves migrate to v3 silently on next save. Existing
  completion progress is preserved; achievement bits initialise to
  zero; reading-speed defaults to Normal; playtime initialises to 0.
- v2 scenarios CANNOT load on v1.x. A v2 scenario opened under
  v1.x rejects with a version-too-new error.
- [meta] version: 3+ scenarios reject on v2.0 with
  ENGINE_ERR_VERSION. Forward-compat reservation for v2.1+.
- F9 / F10 status flash now repaints in the active theme's
  status attribute (was v1.2.1's single hardcoded ATTR_STATUS).
  Per-AI visual variance is intentional: axiom flashes bright
  white, hushline subdued grey, kestrel9 red, orchard cyan, cinder
  magenta. Status row cells diverge from v1.2.1 goldens by design;
  T1 cell-buffer parity is gated on rows 0..23 only (row 24 is
  Phase 11's status bar territory).

Binary
- TAKEOVER.EXE: 63,068 bytes (v1.2.1) -> 146,780 bytes (v2.0). +83 KB.
  The growth is the shell-side TU set (cursor, tag_table, word_wrap,
  theme_apply, theme_state, delay, text_emit, scrollback, audio,
  effects, transitions, input, overlay, menu_card, menu_cards,
  menu_save, status_bar, dat_io, achievements_copy) plus the consumer
  arms and the themes table. The 5 production scenarios still fit in
  the conventional-memory budget on a 320CDT (250 KB free floor;
  v2.0 leaves headroom).
- 0 shell-side DGROUP near-data across all 19 shell translation units
  (Cerberus discipline; every static is static <type> __far <name>).
- 115+ tests across 6 acceptance gates; T1 cell-buffer parity
  preserved byte-for-byte vs v1.2.1 for all 5 production scenarios
  across all 13 phases.

Testing
- DOSBox-Staging full automated test suite green at each phase tag.
- Iron-rig validation: tested on DOSBox-Staging. Iron-rig validation
  on the 320CDT (primary), 386PC (NetISA bootstrap), and 486 NetISA
  is pending; see docs/PHASE13_IRON_TEST_PROTOCOL.md for the
  protocol and docs/PHASE13_IRON_TEST_LOG_TEMPLATE.md for the log
  template. If iron-test surfaces a regression, the fix lands as
  v2.0.1.

---

v1.2.1 (2026-04-25): Bug-fix release

Patch on top of v1.2 the same day, addressing three issues found in the
post-release code review.

Fixed
- Esc / Enter encoding mismatch. KEY_ESC is 0x001B and KEY_ENTER
  is 0x000D in lib/screen.h, but BIOS INT 16h returns the full
  scan/ASCII pair (e.g. 0x011B for Esc on real hardware). The v1.2
  abort and dialog-advance checks worked because every site already had
  a defensive (key & 0xFF) == 0x1B fallback, but the dual checks were
  scattered and brittle. New IS_KEY_ESC and IS_KEY_ENTER helper
  macros in lib/screen.h accept either encoding; all six call sites in
  src/engine.c, src/cracktro.c, and src/menu.c now use the macros.
- Space-during-audio-flash leaked into the outer scenario delay.
  handle_audio_key runs a 600 ms engine_delay after a F9/F10 toggle
  to flash a status hint. If the user pressed Space during that flash,
  the inner delay set g_skip_delay = 1 and returned, but the outer
  scenario delay (the one the user was sitting through when they hit
  F9) then saw the flag still set and skipped early. Now the flag is
  saved before the flash and restored after, so Space during the flash
  skips only the flash, not the outer delay.
- g_skip_delay not reset in engine_reset for symmetry with
  g_abort_requested. No known live bug; defensive only.

Documentation
- New comment on read_input clarifying the buf_max convention
  (chars excluding the NUL; caller storage must be buf_max + 1 bytes).

Compatibility
- v1.2 saves and .scn files are unchanged. v1.2.1 is a drop-in
  replacement.

Binary
- Size: 63,068 bytes (v1.2 was 63,050). +18 bytes.

---

v1.2 (2026-04-25): Robustness & UX Polish

Fixed
- Esc now exits any running scenario. Before this release, scenario
  input loops only handled Enter and the typed characters; engine_delay
  busy-waited on the BIOS tick with no exit path. A user mid-scenario
  who hit Esc got nothing and had to reboot. Esc now sets a global
  abort flag that engine_run honours at the top of the outer state
  loop, returning a new END_QUIT result that skips the
  "Scenario complete" splash and returns to the menu cleanly.
- Engine no longer eats keys typed during delays. The previous
  abort path drained the BIOS keyboard buffer on every poll; any key
  pressed during a long pause was lost before the next input prompt
  saw it. The new check_engine_keys peeks first, consumes only the
  global hotkeys, and leaves everything else for the next read_input
  or show_choices.
- F9 / F10 audio toggles work mid-scenario. Previously they only
  fired when the scenario stopped on a prompt or choice. Now they take
  effect immediately, including during typing animations and long
  scripted pauses.
- Climax sequence drains held keys on early exit. A mashed Esc
  during the Mode 13h climax could leak into the next screen; the
  cleanup loop now flushes the buffer before returning.
- Parser error messages include the scenario filename. Errors that
  used to say "Line 42: malformed state header" now say
  "Error: scn/orchard.scn:42: malformed state header (expected
  [state: name])".

Added
- Space = skip current pause / typing animation. Cuts through
  long scripted delays without aborting the scenario.
- F1 = key reference overlay. Modal box shown on top of the
  current scenario; lists every key the engine handles. Available
  during delays, input prompts, and choice menus. Resumes the
  scenario on any keystroke.
- F9 / F10 mute states persist across runs. TAKEOVER.DAT save file
  bumped to schema v2 with two new bytes (music_muted, sfx_muted).
  v1 saves load with both defaults set to off (the v1 behaviour) and
  upgrade silently on the next write.
- Status bar now lists Esc. "F9:Music F10:Sound" became
  "F9:Mus F10:Snd Esc:Quit" so the new affordance is discoverable
  without reading the README.
- Menu version string updated to v1.2.

Compatibility
- v1.1 TAKEOVER.DAT files load fine; you keep your completion progress
  and start with both audio channels unmuted.
- Scenario .scn files are unchanged; v1.1 scenarios run under v1.2
  with no edits.

Binary
- 63,050 bytes (v1.1 was 60,492). +2,558 bytes.

---

v1.1 (2026-04-13): Demoscene Enhancement Pack

Audio-visual beat sync, OPL2 sound stingers, state transitions
(dissolve, wipe, fade, glitch), sine wave text distortion, VGA palette
cycling in text mode, AI control status bar, per-AI Mode 13h climax
sequences, hidden cracktro with raster bars, DYCP scroller, starfield,
9-channel chiptune. Quality-gated through 5 rounds of adversarial
review (12 bugs fixed). 60.5 KB EXE.

v1.0 (2026-04-13): Original release

Five AI scenarios with branching narratives. Text-mode rendering with
VGA Mode 13h plasma title, AdLib FM ambient music, palette fade
transitions. Hardware auto-detection (VGA / EGA / CGA / MDA, AdLib,
FPU) with graceful degradation. 42 KB EXE. MIT license.
