docs(port-plan): close migration prerequisite gaps
This commit is contained in:
@@ -27,13 +27,13 @@ The 40250 source is the specification. Do not design behavior; transcribe it. Co
|
||||
## Code layout: mirror 40250
|
||||
|
||||
The logic layer has the 40250 structure, not a new architecture. Route, batch order and
|
||||
prerequisites (2A base, 2R pack inventory, 2V vertical slice) are in `docs/PORT-PLAN.md`. `port_map.py` assigns every unit
|
||||
prerequisites (2A base, 2R pack inventory, 2V0-2V3 vertical slices) are in `docs/PORT-PLAN.md`. `port_map.py` assigns every unit
|
||||
one of three layers:
|
||||
|
||||
| Layer | 40250 units | How to port | Where |
|
||||
| --- | --- | --- | --- |
|
||||
| `logic` | `UserInterface/`, `GameLib/`, `EterLib` net/timer/text parsing, `EterPack`, `EterLocale` (everything not listed below) | Copy C++ -> C++. Same file name, class name, method names, member names and statement order; one reference file = one implementation file | `extension/src/port/<Lib>/<File>.{h,cpp}` |
|
||||
| `python` | `Client/Eternexus/root/*.py`, `uiscript/`, `UserInterface/*Module.cpp`, `EterPythonLib/`, `ScriptLib/` | Decided: embedded CPython 2.7.18 runs the scripts unchanged (`docs/PYTHON-EMBED-EVAL.md`, batch 2P); port only the C++ side. Never translate the scripts. Script functions get `RUN_AS_IS` (after the 2A re-baseline), never `N_A`. Reference is 40250 `Eternexus/root`, **not** `assets/root` | `extension/src/port/<Lib>/` (bindings), scripts from pack |
|
||||
| `python` | `Client/Eternexus/root/*.py`, `uiscript/`, `UserInterface/*Module.cpp`, `EterPythonLib/`, `ScriptLib/` | Decided: embedded CPython 2.7.18 runs the scripts unchanged (`docs/PYTHON-EMBED-EVAL.md`, batch 2P); port only the C++ side. Never translate the scripts. Script functions get `RUN_AS_IS` once its evidence gate passes, never `N_A`. Reference is 40250 `Eternexus/root`, **not** `assets/root` | `extension/src/port/<Lib>/` (bindings), scripts from pack |
|
||||
| `platform` | Direct3D/`Grp*`, Granny (`EterGrnLib`), Miles, SpeedTree, `EffectLib`/terrain rendering, Win32 window/input/IME, threads, anti-cheat | Adapter behind the interface the 40250 caller uses; equivalence by observable output | `extension/src/platform/` + existing render code (`metin2_model`, `metin2_anim`, `gr2_bridge`, ...) |
|
||||
|
||||
Rules for the `logic` layer:
|
||||
@@ -48,10 +48,14 @@ Rules for the `logic` layer:
|
||||
switch until the new path is wired into the runtime; delete the old logic in the same commit that
|
||||
switches its callers to the ported code, leaving only glue (node creation, forwarding Godot input,
|
||||
reading ported state to place nodes). A ported function nothing calls at runtime stays `TODO`.
|
||||
- Keep 40250 **widths and overflow semantics**, not its C type names: 40250 is Win32, where `long` and
|
||||
`unsigned long` are 32-bit. Use the fixed-width types from `port/common/Win32Types.h`; every
|
||||
- Keep 40250 **widths and overflow semantics**, not its C type names: the 40250 executable targets
|
||||
32-bit Win32 (ILP32), where `long`, `unsigned long`, and pointers are 32-bit. `Win32Types.h`
|
||||
supplies fixed-width Win32 scalar aliases, but cannot redefine C++ keywords such as `long`;
|
||||
serialized declarations use explicit fixed-width types. Every
|
||||
serialized struct (proto records, packets, EPK index, msa/msm) gets 40250's `#pragma pack` and a
|
||||
`static_assert(sizeof(T) == N)`; pointers stored in `DWORD` become `uintptr_t` with a port-map note.
|
||||
`static_assert(sizeof(T) == N)`. Pointer/handle types stay pointer-sized behind platform adapters;
|
||||
pointers stored in `DWORD` become `uintptr_t` with a port-map note. Arithmetic that relies on
|
||||
32-bit wrap uses unsigned operations or explicit wrapping helpers, never signed-overflow UB.
|
||||
- Keep 40250 units (`TPixelPosition` in cm, `DWORD` ms from `ELTimer_GetMSec`, degrees).
|
||||
Convert to Godot space only in the adapter.
|
||||
- Port in `#include`-dependency order: a shared header belongs to the first unit that needs it, and
|
||||
@@ -97,6 +101,9 @@ conflicts between parallel rounds). Schema in `references/audit-schema.md`. Func
|
||||
|
||||
- `TODO` — not yet compared.
|
||||
- `PORTED` — current counterpart is statement-equivalent; `impl` names it.
|
||||
- `RUN_AS_IS` — Python source is byte-identical to the reference, packaged and loaded by embedded
|
||||
CPython on a reachable runtime path; `impl` names the packaged script and `evidence` names the
|
||||
target-platform import/runtime proof. It is invalid for C++ units.
|
||||
- `ADAPTED` — platform adapter; `note` states both sides and the invariant, with a test.
|
||||
- `N_A` — platform plumbing with no gameplay semantics; `note` states why.
|
||||
- `DIVERGENT` — known different and not yet fixed; `note` says how.
|
||||
|
||||
@@ -124,8 +124,13 @@ One JSON file per 40250 source unit at `audit/port-map/<Lib>/<File>.json`:
|
||||
```
|
||||
|
||||
- Function keys are the reference's qualified names (`Class::Method`, or the free-function name).
|
||||
- `status` is one of `TODO`, `PORTED`, `ADAPTED`, `N_A`, `DIVERGENT`, `NEEDS_LIVE` (meanings in `SKILL.md`).
|
||||
- `impl` is required for `PORTED`/`ADAPTED`/`NEEDS_LIVE`; `note` is required for `ADAPTED`, `N_A`,
|
||||
- `status` is one of `TODO`, `PORTED`, `RUN_AS_IS`, `ADAPTED`, `N_A`, `DIVERGENT`, `NEEDS_LIVE`
|
||||
(meanings in `SKILL.md`).
|
||||
- `RUN_AS_IS` is valid only for a Python script unit whose exact reference bytes are shipped and
|
||||
loaded unchanged by embedded CPython. It requires `impl` (the packaged script path) and a
|
||||
non-empty `evidence` list naming target-platform import/runtime evidence. The unit's
|
||||
`reference_sha256` plus the committed resource manifest bind the evidence to exact source bytes.
|
||||
- `impl` is required for `PORTED`/`RUN_AS_IS`/`ADAPTED`/`NEEDS_LIVE`; `note` is required for `ADAPTED`, `N_A`,
|
||||
`DIVERGENT` and `NEEDS_LIVE`. `ADAPTED` also needs a `test` path.
|
||||
- When `reference_sha256` no longer matches the file, every non-`TODO` function in the unit must be
|
||||
rechecked before the hash is updated.
|
||||
|
||||
@@ -31,8 +31,8 @@ from pathlib import Path
|
||||
import refroot # script directory is on sys.path when run directly
|
||||
from audit_source_coverage import REFERENCE_DIRS, active_project_sources
|
||||
|
||||
STATUSES = ("TODO", "PORTED", "ADAPTED", "N_A", "DIVERGENT", "NEEDS_LIVE")
|
||||
DONE = {"PORTED", "ADAPTED", "N_A"}
|
||||
STATUSES = ("TODO", "PORTED", "RUN_AS_IS", "ADAPTED", "N_A", "DIVERGENT", "NEEDS_LIVE")
|
||||
DONE = {"PORTED", "RUN_AS_IS", "ADAPTED", "N_A"}
|
||||
PY_ROOT = "../../Client/Eternexus/root"
|
||||
UNIT_DIRS = REFERENCE_DIRS + ("EterBase", "EterPythonLib", "ScriptLib", "SpeedTreeLib", "SphereLib", "EterImageLib")
|
||||
PORT_DIR = "extension/src/port"
|
||||
@@ -310,9 +310,15 @@ def cmd_check(repo: Path, units: dict[str, Path], args) -> int:
|
||||
if status not in STATUSES:
|
||||
print(f"ERROR {label}: {fn} has invalid status {status!r}")
|
||||
problems += 1
|
||||
if status in {"PORTED", "ADAPTED", "NEEDS_LIVE"} and not info.get("impl"):
|
||||
if status in {"PORTED", "RUN_AS_IS", "ADAPTED", "NEEDS_LIVE"} and not info.get("impl"):
|
||||
print(f"ERROR {label}: {fn} is {status} without impl")
|
||||
problems += 1
|
||||
if status == "RUN_AS_IS" and (layer(unit) != "python" or not unit.endswith(".py")):
|
||||
print(f"ERROR {label}: {fn} is RUN_AS_IS outside a Python script unit")
|
||||
problems += 1
|
||||
if status == "RUN_AS_IS" and not info.get("evidence"):
|
||||
print(f"ERROR {label}: {fn} is RUN_AS_IS without runtime evidence")
|
||||
problems += 1
|
||||
if status in {"ADAPTED", "N_A", "DIVERGENT", "NEEDS_LIVE"} and not info.get("note"):
|
||||
print(f"ERROR {label}: {fn} is {status} without note")
|
||||
problems += 1
|
||||
|
||||
Reference in New Issue
Block a user