GNU Chess 6.3.0 - native Ensemble 1.x low-memory build
====================================================

This directory is the v0.2 source overlay. It uses the unchanged adapted GNU
Chess engine sources and compiled8086 intermediate in ../engine8086. The
original all-fixed v0.1 build files remain available separately.

REBUILD

From the package SOURCE directory, or from any working directory:

  NASM=/path/to/nasm sh port1/low_memory/rebuild.sh

This requires Python3 and NASM only. It assembles the native shell, generates
fixed lock/return thunks, builds the compatibility runtime, and emits a native
GEOS1 geode using the included genuine GNU Chess engine intermediate.

Optional full engine recompilation:

  export WATCOM=/path/to/openwatcom
  export ROOT_DIR=/path/to/pcgeos-source
  export GEOS_SDK=/path/to/pcgeos-sdk
  export GEOS_HOST_TOOLS=/path/to/patched/goc-and-glue/bin
  NASM=/path/to/nasm sh port1/low_memory/rebuild.sh --compile-engine

If GEOS_HOST_TOOLS is unset, the supplied engine8086 host-tool bootstrap can
build GOC/Glue from ROOT_DIR, applying the bundled host64/debug-map patches.
The30 engine translation units are compiled with Watcom -0. Public bridge
entry offsets are regenerated from the compiler's object listing.

Both routes reproduced the tested224,622-byte candidate exactly:
SHA-256 796ba70122e22276bbeac16ef55fa9bed87d525419072446df3afff6137d5c62

The engine is compiled for16-bit registers. The shell and lock thunks use
PUSHA and immediate-count shifts. This is not a claim of8086 hardware support
for the complete application; the supplied emulator tests use a later PC CPU.

MEMORY AND RESOURCE POLICY

The previous all-fixed build reserves261,840 bytes of fixed initialized
resources plus its process stack. The new layout reserves183,392 bytes by
that same calculation:78,448 bytes (76.6KiB) less before native UI overhead.
This is a structural figure; real kernel/app allocations are measured by the
separate native memory tests.

Resources26..54 contain83,952 bytes of genuine engine code. They are now
preloaded, movable and swapable, but explicitly nondiscardable: flags0x0a50.
The supplied1.2 kernel's MemLock ordinal5 can swap a block back in but does
not reload a discarded code resource. Restoring0x0a72 discardable code is
therefore not a supported option for this bridge.

Native shell25, runtime59, raw function-pointer callback resource2, fixed
engine data3..24, arena60 and generated thunk resource61 remain fixed. Every
incoming engine far call to resources26..54 is redirected through a thunk.
The builder rejects raw segment/far pointers to those movable code resources.
It uses explicit assembler fixup labels, never instruction-byte scanning.

C-STACK-TRANSPARENT CALLS

A generated thunk saves FLAGS, PUSHA, DS and ES (22 bytes). It locks its target
through a stable resource HANDLE relocation, then records and replaces only
the original far return address. The target's C arguments retain exactly
their original positions. A far jump enters the newly resolved segment.

The target can return with RETF (cdecl caller cleanup) or RETF N (Pascal
callee cleanup). Fixed cleanup saves all returned16-bit registers and FLAGS,
unlocks the finished target, then jumps to the original caller without
changing its post-return SP. A caller's own outer resource remains locked
until that caller returns. Private intra-resource calls remain protected
by that outer lock.

The120 unique target thunks occupy3,456 padded bytes including their common
entry/cleanup code. Handles remain valid when code moves or swaps; resolved
segments are used only while the corresponding lock is held.

Dgroup layout:
  0x2140          native1.x process class
  0x2200..0x2347  existing native shell state
  0x2400          active context depth
  0x2402          context records {returnIP, returnCS, lockedHandle},6 bytes
  0x2a10          target far-jump scratch pointer
  0x2a14          original-caller far-jump scratch pointer
  0x2c00          initialized Dgroup end /1.x TPD_stackBot
  0xc000          unchanged48KiB process stack allocation

The active context limit is128, below the kernel's8-bit resource-lock count
limit. Overflow, cleanup underflow and MemLock failure have explicit fatal
paths; they never fabricate arbitrary C return values. Context depth is
published only after a successful lock.

The bridge is specific to this engine's ABI: entry and return DS is its
private Dgroup, and only its process engine thread uses the context stack.
The executable is single-instance (0x9200 in both header copies), matching
the original GNU Chess .gp single declaration. It is not a general bridge
for arbitrary routines that return with a different DS.

VALIDATION

The original engine host rule tests remain unchanged. New tests exercise:

- Twenty independent16-bit ABI cases, including RETF/RETF N argument cleanup,
  returned registers/FLAGS, nested same-resource calls, lock failure,
  context overflow and cleanup underflow.
- The actual converted low-memory geode's Open/initialization, editable moves,
  illegal-move immutability, engine replies, Undo, depth4 and16-ply self-play.
  The CPU harness moved eligible code at190,837 lock entries and poisoned it
  after final unlock; all resource locks and context entries balanced.
- Separate native Ensemble tests check the actual kernel, GUI, app switching
  and measured memory. See the package test evidence for those results.

CPU test kernel hooks are not a substitute for native runtime validation.
To rerun CPU tests, install Unicorn2.1-compatible Python bindings, then run
from SOURCE:

  python3 port1/low_memory/audit/test_thunk_abi_independent.py
  python3 port1/low_memory/tests/test_engine.py port1/low_memory/dist/GNUCHESS.GEO

The full moving-code CPU test can take about two minutes. Earlier v0.1
engine-only/direct-call harnesses do not understand the new resource61
lock/cleanup bridge; use these low-memory tests for this executable.
