research: map reference sources
Browse files- README.md +4 -0
- assets/analysis/source-map.json +3 -0
- docs/API_INDEX.md +439 -0
- docs/DEPENDENCIES.md +83 -0
- docs/FINDINGS.md +17 -1
- docs/FORMATS.md +82 -0
- docs/HOST_APIS.md +64 -0
- docs/PLUGINS.md +70 -0
- docs/PLUGIN_INDEX.md +358 -0
- docs/README.md +5 -3
- docs/REVERSE_ENGINEERING.md +1 -1
- docs/TODO.md +14 -7
- docs/decisions/D01-source-mapping.md +7 -0
- docs/experiments/static-map-2026-10-21.md +34 -0
- docs/parity.md +35 -0
- docs/risks.md +19 -0
- docs/validation.md +15 -0
- flake.nix +2 -0
- scripts/map_references.py +413 -0
- tests/test_map_references.py +87 -0
README.md
CHANGED
|
@@ -58,3 +58,7 @@ shasum -a 256 -c assets/references/SHA256SUMS
|
|
| 58 |
Commit code and pointer files together with ordinary `git add` / `git commit` / `git push hf main`. The pre-commit hook checks staged storage and filter configuration; pre-push checks new history, then invokes the LFS/Xet upload. `assets-fetch` hydrates files for the checked-out revision; `assets-check` verifies every payload against its staged pointer identity. No separate dataset, branch, or asset lockfile is required: the Git revision pins the pointers.
|
| 59 |
|
| 60 |
See [setup validation](docs/SETUP.md) for the implementation, checks, and remaining platform coverage.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 58 |
Commit code and pointer files together with ordinary `git add` / `git commit` / `git push hf main`. The pre-commit hook checks staged storage and filter configuration; pre-push checks new history, then invokes the LFS/Xet upload. `assets-fetch` hydrates files for the checked-out revision; `assets-check` verifies every payload against its staged pointer identity. No separate dataset, branch, or asset lockfile is required: the Git revision pins the pointers.
|
| 59 |
|
| 60 |
See [setup validation](docs/SETUP.md) for the implementation, checks, and remaining platform coverage.
|
| 61 |
+
|
| 62 |
+
## Source research
|
| 63 |
+
|
| 64 |
+
`map-references` verifies the recovered inputs and regenerates the Xet-backed static source map plus the Core/tool Markdown indexes. `check-reference-map` checks that they are reproducible and current. No original compiler or executable runs. Start with [formats](docs/FORMATS.md), [host APIs](docs/HOST_APIS.md), [plugins](docs/PLUGINS.md), [dependencies](docs/DEPENDENCIES.md), and the [coverage ledger](docs/parity.md). Runtime behavior remains to be verified.
|
assets/analysis/source-map.json
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:e69e1cde985c2b93675a5b964d3de74b6fd15b02b6a1b3f69800800beaeb3095
|
| 3 |
+
size 10566628
|
docs/API_INDEX.md
ADDED
|
@@ -0,0 +1,439 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Core interrupt index
|
| 2 |
+
|
| 3 |
+
Source-only endpoint enumeration for build `2016-03-10-c`. IDs are evaluated source constants, not a binary dispatch trace. Full signatures, arguments and older builds are in [source-map.json](../assets/analysis/source-map.json). See [HOST_APIS.md](HOST_APIS.md).
|
| 4 |
+
|
| 5 |
+
## Akula.ixpl
|
| 6 |
+
|
| 7 |
+
Source: `data/sources/include/core/Akula.ixpl`; SHA-256 `31d8722ad297c40b03420cd66c152f3ca20c7d2d11c16a11716fe28fd1a796da`.
|
| 8 |
+
|
| 9 |
+
| ID | Constant(s) | Wrapper(s), source lines |
|
| 10 |
+
| ---: | --- | --- |
|
| 11 |
+
| 0 | `INT_CHECK_CORE_VERSION` | `checkCoreVersion`:707 |
|
| 12 |
+
| 1 | `INT_REGISTER_TOOL` | `registerTool`:708 |
|
| 13 |
+
| 2 | `INT_SET_RUNTIME_ON_ALL_LOADED` | `setRuntimeOnAllLoaded`:709 |
|
| 14 |
+
| 3 | `INT_SET_RUNTIME_ON_FINALIZATION` | `setRuntimeOnFinalization`:710 |
|
| 15 |
+
| 4 | `INT_SET_RUNTIME_VIEW_CLONE_ACTION` | `setRuntimeViewCloneAction`:711 |
|
| 16 |
+
| 5 | `INT_SET_RUNTIME_VIEW_CLOSE_ACTION` | `setRuntimeViewCloseAction`:712 |
|
| 17 |
+
| 6 | `INT_SET_RUNTIME_ON_VIEW_SELECTED` | `setRuntimeOnViewSelected`:713 |
|
| 18 |
+
| 7 | `INT_SET_RUNTIME_ON_VIEW_MOUSE_MOVE` | `setRuntimeOnViewMouseMove`:714 |
|
| 19 |
+
| 8 | `INT_SET_RUNTIME_ON_CAMERA_UPDATE_TICK` | `setRuntimeOnCameraUpdateTick`:715 |
|
| 20 |
+
| 9 | `INT_TRANSLATE` | `translate`:716, `translate`:957 |
|
| 21 |
+
| 10 | `INT_GET_TOOL_ID` | `getToolID`:717 |
|
| 22 |
+
| 11 | `INT_GET_TOOL_NAME` | `getToolName`:718, `getToolName`:958 |
|
| 23 |
+
| 12 | `INT_QUEUE_TASK` | `queueTask`:719 |
|
| 24 |
+
| 13 | `INT_GET_TASK_BUF_I` | `getTaskBufI`:720 |
|
| 25 |
+
| 14 | `INT_GET_TASK_BUF_L` | `getTaskBufL`:721 |
|
| 26 |
+
| 15 | `INT_GET_TASK_BUF_F` | `getTaskBufF`:722 |
|
| 27 |
+
| 16 | `INT_GET_TASK_BUF_D` | `getTaskBufD`:723 |
|
| 28 |
+
| 17 | `INT_GET_TASK_BUF_V3` | `getTaskBufVec3`:724 |
|
| 29 |
+
| 18 | `INT_LOAD_TEXT_FILE` | `loadTextFile`:725 |
|
| 30 |
+
| 19 | `INT_SAVE_TEXT_FILE` | `saveTextFile`:726 |
|
| 31 |
+
| 20 | `INT_LOAD_CONFIG_FILE` | `loadConfigFile`:727 |
|
| 32 |
+
| 21 | `INT_SAVE_CONFIG_FILE` | `saveConfigFile`:728 |
|
| 33 |
+
| 22 | `INT_TEXT_INPUT_BOX` | `textInputBox`:729 |
|
| 34 |
+
| 23 | `INT_TEXT_OUTPUT_BOX` | `textOutputBox`:730 |
|
| 35 |
+
| 24 | `INT_TOGGLE_FULLSCREEN` | `toggleFullscreen`:731 |
|
| 36 |
+
| 25 | `INT_TOGGLE_FAKE_FULLSCREEN` | `toggleFakeFullscreen`:732 |
|
| 37 |
+
| 26 | `INT_DISPLAY_TEXT_WIDTH` | `displayTextWidth`:733 |
|
| 38 |
+
| 27 | `INT_DISPLAY_TEXT_HEIGHT` | `displayTextHeight`:734 |
|
| 39 |
+
| 28 | `INT_SET_MOUSE_POSITION` | `setMousePosition`:735 |
|
| 40 |
+
| 29 | `INT_GET_MOUSE_POSITION` | `getMousePosition`:736, `getMousePosition`:959 |
|
| 41 |
+
| 30 | `INT_ESCAPE_DISPLAY_TEXT` | `escapeDisplayText`:737, `escapeDisplayText`:960 |
|
| 42 |
+
| 31 | `INT_UNESCAPE_DISPLAY_TEXT` | `unescapeDisplayText`:738, `unescapeDisplayText`:961 |
|
| 43 |
+
| 32 | `INT_CROP_DISPLAY_TEXT` | `cropDisplayText`:739, `cropDisplayText`:962 |
|
| 44 |
+
| 33 | `INT_WRAP_DISPLAY_TEXT` | `wrapDisplayText`:740, `wrapDisplayText`:963 |
|
| 45 |
+
| 34 | `INT_SET_BACKGROUND_COLOR` | `setBackgroundColor`:741 |
|
| 46 |
+
| 35 | `INT_SET_FALLBACK_LANGUAGE` | `setFallbackLanguage`:742 |
|
| 47 |
+
| 36 | `INT_SET_FONT_PATH` | `setFontPath`:743 |
|
| 48 |
+
| 37 | `INT_SET_SCREEN_REFRESH_RATE` | `setScreenRefreshRate`:745 |
|
| 49 |
+
| 38 | `INT_SET_LANGUAGE` | `setLanguage`:744 |
|
| 50 |
+
| 39 | `INT_SET_GUI_ACTIVE_COLOR` | `setGUIActiveColor`:746 |
|
| 51 |
+
| 40 | `INT_SET_GUI_ACTIVE_RESET_STRING` | `setGUIActiveResetString`:747 |
|
| 52 |
+
| 41 | `INT_SET_GUI_CHAR_HEIGHT` | `setGUICharHeight`:748 |
|
| 53 |
+
| 42 | `INT_SET_GUI_CHAR_TEXELS_U` | `setGUICharTexelsU`:749 |
|
| 54 |
+
| 43 | `INT_SET_GUI_CHAR_TEXELS_V` | `setGUICharTexelsV`:750 |
|
| 55 |
+
| 44 | `INT_SET_GUI_CHAR_WIDTH` | `setGUICharWidth`:751 |
|
| 56 |
+
| 45 | `INT_SET_GUI_CONNECTION_COLOR` | `setGUIConnectionColor`:752 |
|
| 57 |
+
| 46 | `INT_SET_GUI_CONNECTION_WIDTH` | `setGUIConnectionWidth`:753 |
|
| 58 |
+
| 47 | `INT_SET_GUI_CORNER_SIZE` | `setGUICornerSize`:754 |
|
| 59 |
+
| 48 | `INT_SET_GUI_HIGHLIGHT_COLOR` | `setGUIHighlightColor`:755 |
|
| 60 |
+
| 49 | `INT_SET_GUI_INACTIVE_RESET_STRING` | `setGUIInactiveResetString`:756 |
|
| 61 |
+
| 50 | `INT_SET_GUI_MAIN_COLOR` | `setGUIMainColor`:757 |
|
| 62 |
+
| 51 | `INT_SET_GUI_VIEW_BORDER_SIZE` | `setGUIViewBorderSize`:758 |
|
| 63 |
+
| 52 | `INT_LOAD_GUI_TEXTURE` | `loadGUITexture`:759 |
|
| 64 |
+
| 53 | `INT_DISCARD_GUI_TEXTURE` | `discardGUITexture`:760 |
|
| 65 |
+
| 54 | `INT_QUERY_GUI_TEXTURE_PARAMS` | `queryGUITextureParams`:761 |
|
| 66 |
+
| 55 | `INT_GET_BACKGROUND_COLOR` | `getBackgroundColor`:762 |
|
| 67 |
+
| 56 | `INT_GET_FALLBACK_LANGUAGE` | `getFallbackLanguage`:763, `getFallbackLanguage`:964 |
|
| 68 |
+
| 57 | `INT_GET_FONT_PATH` | `getFontPath`:764, `getFontPath`:965 |
|
| 69 |
+
| 58 | `INT_GET_LANGUAGE` | `getLanguage`:765, `getLanguage`:966 |
|
| 70 |
+
| 59 | `INT_GET_SCREEN_REFRESH_RATE` | `getScreenRefreshRate`:766 |
|
| 71 |
+
| 60 | `INT_GET_GUI_ACTIVE_COLOR` | `getGUIActiveColor`:767 |
|
| 72 |
+
| 61 | `INT_GET_GUI_ACTIVE_RESET_STRING` | `getGUIActiveResetString`:768, `getGUIActiveResetString`:967 |
|
| 73 |
+
| 62 | `INT_GET_GUI_CHAR_HEIGHT` | `getGUICharHeight`:769 |
|
| 74 |
+
| 63 | `INT_GET_GUI_CHAR_TEXELS_U` | `getGUICharTexelsU`:770 |
|
| 75 |
+
| 64 | `INT_GET_GUI_CHAR_TEXELS_V` | `getGUICharTexelsV`:771 |
|
| 76 |
+
| 65 | `INT_GET_GUI_CHAR_WIDTH` | `getGUICharWidth`:772 |
|
| 77 |
+
| 66 | `INT_GET_GUI_CONNECTION_COLOR` | `getGUIConnectionColor`:773 |
|
| 78 |
+
| 67 | `INT_GET_GUI_CONNECTION_WIDTH` | `getGUIConnectionWidth`:774 |
|
| 79 |
+
| 68 | `INT_GET_GUI_CORNER_SIZE` | `getGUICornerSize`:775 |
|
| 80 |
+
| 69 | `INT_GET_GUI_HIGHLIGHT_COLOR` | `getGUIHighlightColor`:776 |
|
| 81 |
+
| 70 | `INT_GET_GUI_INACTIVE_RESET_STRING` | `getGUIInactiveResetString`:777, `getGUIInactiveResetString`:968 |
|
| 82 |
+
| 71 | `INT_GET_GUI_MAIN_COLOR` | `getGUIMainColor`:778 |
|
| 83 |
+
| 72 | `INT_GET_GUI_VIEW_BORDER_SIZE` | `getGUIViewBorderSize`:779 |
|
| 84 |
+
| 73 | `INT_GET_NEXT_FALLBACK_LANGUAGE` | `getNextFallbackLanguage`:780, `getNextFallbackLanguage`:969 |
|
| 85 |
+
| 74 | `INT_GET_NEXT_FONT_PATH` | `getNextFontPath`:781, `getNextFontPath`:970 |
|
| 86 |
+
| 75 | `INT_GET_NEXT_LANGUAGE` | `getNextLanguage`:782, `getNextLanguage`:971 |
|
| 87 |
+
| 76 | `INT_GET_NEXT_GUI_ACTIVE_COLOR` | `getNextGUIActiveColor`:783 |
|
| 88 |
+
| 77 | `INT_GET_NEXT_GUI_ACTIVE_RESET_STRING` | `getNextGUIActiveResetString`:784, `getNextGUIActiveResetString`:972 |
|
| 89 |
+
| 78 | `INT_GET_NEXT_GUI_CHAR_HEIGHT` | `getNextGUICharHeight`:785 |
|
| 90 |
+
| 79 | `INT_GET_NEXT_GUI_CHAR_TEXELS_U` | `getNextGUICharTexelsU`:786 |
|
| 91 |
+
| 80 | `INT_GET_NEXT_GUI_CHAR_TEXELS_V` | `getNextGUICharTexelsV`:787 |
|
| 92 |
+
| 81 | `INT_GET_NEXT_GUI_CHAR_WIDTH` | `getNextGUICharWidth`:788 |
|
| 93 |
+
| 82 | `INT_GET_NEXT_GUI_CORNER_SIZE` | `getNextGUICornerSize`:789 |
|
| 94 |
+
| 83 | `INT_GET_NEXT_GUI_HIGHLIGHT_COLOR` | `getNextGUIHighlightColor`:790 |
|
| 95 |
+
| 84 | `INT_GET_NEXT_GUI_INACTIVE_RESET_STRING` | `getNextGUIInactiveResetString`:791, `getNextGUIInactiveResetString`:973 |
|
| 96 |
+
| 85 | `INT_GET_NEXT_GUI_MAIN_COLOR` | `getNextGUIMainColor`:792 |
|
| 97 |
+
| 86 | `INT_GET_NEXT_GUI_VIEW_BORDER_SIZE` | `getNextGUIViewBorderSize`:793 |
|
| 98 |
+
| 87 | `INT_HAS_CONFIG_CHANGED` | `hasConfigChanged`:794 |
|
| 99 |
+
| 88 | `INT_HAS_DEFERRED_CONFIG_CHANGES` | `hasDeferredConfigChanges`:795 |
|
| 100 |
+
| 89 | `INT_MAKE_WINDOW` | `makeWindow`:796 |
|
| 101 |
+
| 90 | `INT_DESTROY_WINDOW` | `destroyWindow`:797 |
|
| 102 |
+
| 91 | `INT_SELECT_PARENT_WINDOW` | `selectParentWindow`:798 |
|
| 103 |
+
| 92 | `INT_SET_MIN_WINDOW_DIMENSIONS` | `setMinWindowDimensions`:799 |
|
| 104 |
+
| 93 | `INT_WINDOW_RENDER_ALL` | `windowRenderAll`:800 |
|
| 105 |
+
| 94 | `INT_WINDOW_RENDER` | `windowRender`:801 |
|
| 106 |
+
| 95 | `INT_WINDOW_SET_RG_TEXTURE` | `windowSetRGTexture`:802 |
|
| 107 |
+
| 96 | `INT_WINDOW_CLEAR_RG_TEXTURE` | `windowClearRGTexture`:803 |
|
| 108 |
+
| 97 | `INT_SET_WINDOW_POSITION` | `setWindowPosition`:804 |
|
| 109 |
+
| 98 | `INT_GET_WINDOW_POSITION` | `getWindowPosition`:805, `getWindowPosition`:974 |
|
| 110 |
+
| 99 | `INT_SET_WINDOW_DIMENSIONS` | `setWindowDimensions`:806 |
|
| 111 |
+
| 100 | `INT_GET_WINDOW_DIMENSIONS` | `getWindowDimensions`:807, `getWindowDimensions`:975 |
|
| 112 |
+
| 101 | `INT_BRING_WINDOW_TO_FRONT` | `bringWindowToFront`:808 |
|
| 113 |
+
| 102 | `INT_SEND_WINDOW_TO_BACK` | `sendWindowToBack`:809 |
|
| 114 |
+
| 103 | `INT_QUERY_IS_WINDOW_AT_FRONT` | `queryIsWindowAtFront`:810 |
|
| 115 |
+
| 104 | `INT_QUERY_IS_WINDOW_AT_BACK` | `queryIsWindowAtBack`:811 |
|
| 116 |
+
| 105 | `INT_QUERY_WINDOW_DRAW_ORDER` | `queryWindowDrawOrder`:812 |
|
| 117 |
+
| 106 | `INT_QUERY_IS_WINDOW_OBSTRUCTED` | `queryIsWindowObstructed`:813 |
|
| 118 |
+
| 107 | `INT_QUERY_IS_WINDOW_IN_CLIENT_AREA` | `queryIsWindowInClientArea`:814 |
|
| 119 |
+
| 108 | `INT_SET_WINDOW_DEPTH_LAYER` | `setWindowDepthLayer`:815 |
|
| 120 |
+
| 109 | `INT_GET_WINDOW_DEPTH_LAYER` | `getWindowDepthLayer`:816 |
|
| 121 |
+
| 110 | `INT_MAKE_BUTTON` | `makeButton`:817 |
|
| 122 |
+
| 111 | `INT_MAKE_CHECKBOX` | `makeCheckbox`:818 |
|
| 123 |
+
| 112 | `INT_MAKE_EDIT` | `makeEdit`:819 |
|
| 124 |
+
| 113 | `INT_MAKE_LABEL` | `makeLabel`:820 |
|
| 125 |
+
| 114 | `INT_MAKE_RADIO` | `makeRadio`:821 |
|
| 126 |
+
| 115 | `INT_MAKE_FILL_RECT` | `makeFillRect`:822 |
|
| 127 |
+
| 116 | `INT_MAKE_IMAGE` | `makeImage`:823 |
|
| 128 |
+
| 117 | `INT_MAKE_TILT_LEFT` | `makeTiltLeft`:824 |
|
| 129 |
+
| 118 | `INT_DESTROY_CONTROL` | `destroyControl`:825 |
|
| 130 |
+
| 119 | `INT_SET_CONTROL_ACTIVE` | `setControlActive`:826 |
|
| 131 |
+
| 120 | `INT_IS_CONTROL_ACTIVE` | `isControlActive`:827 |
|
| 132 |
+
| 121 | `INT_SET_CONTROL_POSITION` | `setControlPosition`:828 |
|
| 133 |
+
| 122 | `INT_GET_CONTROL_POSITION` | `getControlPosition`:829, `getControlPosition`:976 |
|
| 134 |
+
| 123 | `INT_SET_CONTROL_DIMENSIONS` | `setControlDimensions`:830 |
|
| 135 |
+
| 124 | `INT_GET_CONTROL_DIMENSIONS` | `getControlDimensions`:831, `getControlDimensions`:977 |
|
| 136 |
+
| 125 | `INT_SET_CONTROL_TEXT` | `setControlText`:832 |
|
| 137 |
+
| 126 | `INT_GET_CONTROL_TEXT` | `getControlText`:833, `getControlText`:978 |
|
| 138 |
+
| 127 | `INT_SET_CHECKBOX_CHECKED` | `setCheckboxChecked`:834 |
|
| 139 |
+
| 128 | `INT_IS_CHECKBOX_CHECKED` | `isCheckboxChecked`:835 |
|
| 140 |
+
| 129 | `INT_SET_RADIO_SELECTED` | `setRadioSelected`:836 |
|
| 141 |
+
| 130 | `INT_IS_RADIO_SELECTED` | `isRadioSelected`:837 |
|
| 142 |
+
| 131 | `INT_SET_CONTROL_HANDLER` | `setControlHandler`:838 |
|
| 143 |
+
| 132 | `INT_SET_CONTROL_HANDLER_ALT` | `setControlHandlerAlt`:839 |
|
| 144 |
+
| 133 | `INT_SET_WINDOW_BEGIN_USE_HANDLER` | `setWindowBeginUseHandler`:840 |
|
| 145 |
+
| 134 | `INT_SET_WINDOW_MOVE_HANDLER` | `setWindowMoveHandler`:841 |
|
| 146 |
+
| 135 | `INT_SET_WINDOW_RESIZE_HANDLER` | `setWindowResizeHandler`:842 |
|
| 147 |
+
| 136 | `INT_SET_WINDOW_SHORTCUT_HANDLER` | `setWindowShortcutHandler`:843 |
|
| 148 |
+
| 137 | `INT_PROCESS_BASE_KEY_CONFIG` | `processBaseKeyConfig`:844, `processBaseKeyConfig`:979 |
|
| 149 |
+
| 138 | `INT_PUSH_BASE_KEY_CONFIG` | `pushBaseKeyConfig`:845 |
|
| 150 |
+
| 139 | `INT_POP_BASE_KEY_CONFIG` | `popBaseKeyConfig`:846 |
|
| 151 |
+
| 140 | `INT_COMMIT_BASE_KEY_CONFIG` | `commitBaseKeyConfig`:847 |
|
| 152 |
+
| 141 | `INT_QUERY_BASE_KEY_CONFIG_BINDINGS` | `queryBaseKeyConfigBindings`:848, `queryBaseKeyConfigBindings`:980 |
|
| 153 |
+
| 142 | `INT_PROCESS_FLY_KEY_CONFIG` | `processFlyKeyConfig`:849, `processFlyKeyConfig`:981 |
|
| 154 |
+
| 143 | `INT_PUSH_FLY_KEY_CONFIG` | `pushFlyKeyConfig`:850 |
|
| 155 |
+
| 144 | `INT_POP_FLY_KEY_CONFIG` | `popFlyKeyConfig`:851 |
|
| 156 |
+
| 145 | `INT_COMMIT_FLY_KEY_CONFIG` | `commitFlyKeyConfig`:852 |
|
| 157 |
+
| 146 | `INT_QUERY_FLY_KEY_CONFIG_BINDINGS` | `queryFlyKeyConfigBindings`:853, `queryFlyKeyConfigBindings`:982 |
|
| 158 |
+
| 147 | `INT_SELECT_VIEW` | `selectView`:854 |
|
| 159 |
+
| 148 | `INT_GET_CURRENT_VIEW` | `getCurrentView`:855 |
|
| 160 |
+
| 149 | `INT_GET_WORLD_FOR_VIEW` | `getWorldForView`:856 |
|
| 161 |
+
| 150 | `INT_GET_VIEW_COUNT_FOR_WORLD` | `getViewCountForWorld`:857 |
|
| 162 |
+
| 151 | `INT_GET_VIEWS_FOR_WORLD` | `getViewsForWorld`:858 |
|
| 163 |
+
| 152 | `INT_GET_TOPMOST_VIEW_FOR_WORLD` | `getTopmostViewForWorld`:859 |
|
| 164 |
+
| 153 | `INT_CLONE_VIEW` | `cloneView`:860 |
|
| 165 |
+
| 154 | `INT_MINIMIZE_VIEW` | `minimizeView`:861 |
|
| 166 |
+
| 155 | `INT_IS_VIEW_MINIMIZED` | `isViewMinimized`:862 |
|
| 167 |
+
| 156 | `INT_MAXIMIZE_VIEW` | `maximizeView`:863 |
|
| 168 |
+
| 157 | `INT_IS_VIEW_MAXIMIZED` | `isViewMaximized`:864 |
|
| 169 |
+
| 158 | `INT_RESTORE_VIEW` | `restoreView`:865 |
|
| 170 |
+
| 159 | `INT_TOGGLE_VIEW_FOCUS_LOCK` | `toggleViewFocusLock`:866 |
|
| 171 |
+
| 160 | `INT_CLOSE_VIEW` | `closeView`:867 |
|
| 172 |
+
| 161 | `INT_GET_CURRENT_VIEW_COUNT` | `getCurrentViewCount`:868 |
|
| 173 |
+
| 162 | `INT_GET_MAX_VIEW_COUNT` | `getMaxViewCount`:869 |
|
| 174 |
+
| 163 | `INT_SET_VIEW_POSITION` | `setViewPosition`:870 |
|
| 175 |
+
| 164 | `INT_GET_VIEW_POSITION` | `getViewPosition`:871, `getViewPosition`:983 |
|
| 176 |
+
| 165 | `INT_SET_VIEW_DIMENSIONS` | `setViewDimensions`:872 |
|
| 177 |
+
| 166 | `INT_GET_VIEW_DIMENSIONS` | `getViewDimensions`:873, `getViewDimensions`:984 |
|
| 178 |
+
| 167 | `INT_SET_VIEW_TITLE` | `setViewTitle`:874 |
|
| 179 |
+
| 168 | `INT_GET_VIEW_TITLE` | `getViewTitle`:875, `getViewTitle`:985 |
|
| 180 |
+
| 169 | `INT_SET_VIEW_BACKGROUND_COLOR` | `setViewBackgroundColor`:876 |
|
| 181 |
+
| 170 | `INT_GET_VIEW_BACKGROUND_COLOR` | `getViewBackgroundColor`:877 |
|
| 182 |
+
| 171 | `INT_SET_VIEW_PROJECTION_QUAD` | `setViewProjectionQuad`:878 |
|
| 183 |
+
| 172 | `INT_GET_VIEW_PROJECTION_QUAD` | `getViewProjectionQuad`:879 |
|
| 184 |
+
| 173 | `INT_SET_FLYING` | `setFlying`:880 |
|
| 185 |
+
| 174 | `INT_IS_FLYING` | `isFlying`:881 |
|
| 186 |
+
| 175 | `INT_FLY_FORWARD` | `flyForward`:882 |
|
| 187 |
+
| 176 | `INT_FLY_BACKWARD` | `flyBackward`:883 |
|
| 188 |
+
| 177 | `INT_FLY_LEFT` | `flyLeft`:884 |
|
| 189 |
+
| 178 | `INT_FLY_RIGHT` | `flyRight`:885 |
|
| 190 |
+
| 179 | `INT_FLY_UP` | `flyUp`:886 |
|
| 191 |
+
| 180 | `INT_FLY_DOWN` | `flyDown`:887 |
|
| 192 |
+
| 181 | `INT_TURN_LEFT` | `turnLeft`:888 |
|
| 193 |
+
| 182 | `INT_TURN_RIGHT` | `turnRight`:889 |
|
| 194 |
+
| 183 | `INT_LOOK_UP` | `lookUp`:890 |
|
| 195 |
+
| 184 | `INT_LOOK_DOWN` | `lookDown`:891 |
|
| 196 |
+
| 185 | `INT_LEAN_LEFT` | `leanLeft`:892 |
|
| 197 |
+
| 186 | `INT_LEAN_RIGHT` | `leanRight`:893 |
|
| 198 |
+
| 187 | `INT_MOUSE_X_FLY_FORWARD` | `mouseXFlyForward`:894 |
|
| 199 |
+
| 188 | `INT_MOUSE_X_FLY_BACKWARD` | `mouseXFlyBackward`:895 |
|
| 200 |
+
| 189 | `INT_MOUSE_X_FLY_LEFT` | `mouseXFlyLeft`:896 |
|
| 201 |
+
| 190 | `INT_MOUSE_X_FLY_RIGHT` | `mouseXFlyRight`:897 |
|
| 202 |
+
| 191 | `INT_MOUSE_X_FLY_UP` | `mouseXFlyUp`:898 |
|
| 203 |
+
| 192 | `INT_MOUSE_X_FLY_DOWN` | `mouseXFlyDown`:899 |
|
| 204 |
+
| 193 | `INT_MOUSE_X_TURN_LEFT` | `mouseXTurnLeft`:900 |
|
| 205 |
+
| 194 | `INT_MOUSE_X_TURN_RIGHT` | `mouseXTurnRight`:901 |
|
| 206 |
+
| 195 | `INT_MOUSE_X_LOOK_UP` | `mouseXLookUp`:902 |
|
| 207 |
+
| 196 | `INT_MOUSE_X_LOOK_DOWN` | `mouseXLookDown`:903 |
|
| 208 |
+
| 197 | `INT_MOUSE_X_LEAN_LEFT` | `mouseXLeanLeft`:904 |
|
| 209 |
+
| 198 | `INT_MOUSE_X_LEAN_RIGHT` | `mouseXLeanRight`:905 |
|
| 210 |
+
| 199 | `INT_MOUSE_Y_FLY_FORWARD` | `mouseYFlyForward`:906 |
|
| 211 |
+
| 200 | `INT_MOUSE_Y_FLY_BACKWARD` | `mouseYFlyBackward`:907 |
|
| 212 |
+
| 201 | `INT_MOUSE_Y_FLY_LEFT` | `mouseYFlyLeft`:908 |
|
| 213 |
+
| 202 | `INT_MOUSE_Y_FLY_RIGHT` | `mouseYFlyRight`:909 |
|
| 214 |
+
| 203 | `INT_MOUSE_Y_FLY_UP` | `mouseYFlyUp`:910 |
|
| 215 |
+
| 204 | `INT_MOUSE_Y_FLY_DOWN` | `mouseYFlyDown`:911 |
|
| 216 |
+
| 205 | `INT_MOUSE_Y_TURN_LEFT` | `mouseYTurnLeft`:912 |
|
| 217 |
+
| 206 | `INT_MOUSE_Y_TURN_RIGHT` | `mouseYTurnRight`:913 |
|
| 218 |
+
| 207 | `INT_MOUSE_Y_LOOK_UP` | `mouseYLookUp`:914 |
|
| 219 |
+
| 208 | `INT_MOUSE_Y_LOOK_DOWN` | `mouseYLookDown`:915 |
|
| 220 |
+
| 209 | `INT_MOUSE_Y_LEAN_LEFT` | `mouseYLeanLeft`:916 |
|
| 221 |
+
| 210 | `INT_MOUSE_Y_LEAN_RIGHT` | `mouseYLeanRight`:917 |
|
| 222 |
+
| 211 | `INT_SET_CAM_POSITION` | `setCamPosition`:918 |
|
| 223 |
+
| 212 | `INT_GET_CAM_POSITION` | `getCamPosition`:919 |
|
| 224 |
+
| 213 | `INT_SET_CAM_ORIENTATION` | `setCamOrientation`:920 |
|
| 225 |
+
| 214 | `INT_GET_CAM_ORIENTATION` | `getCamOrientation`:921 |
|
| 226 |
+
| 215 | `INT_SET_CAM_OFFSET` | `setCamOffset`:922 |
|
| 227 |
+
| 216 | `INT_GET_CAM_OFFSET` | `getCamOffset`:923 |
|
| 228 |
+
| 217 | `INT_SET_CAM_BASE_ORIENTATION` | `setCamBaseOrientation`:924 |
|
| 229 |
+
| 218 | `INT_GET_CAM_BASE_ORIENTATION` | `getCamBaseOrientation`:925 |
|
| 230 |
+
| 219 | `INT_GET_MAIN_RAY` | `getMainRay`:926 |
|
| 231 |
+
| 220 | `INT_GET_MOUSE_RAY` | `getMouseRay`:927 |
|
| 232 |
+
| 221 | `INT_VIS_MAKE_MESH` | `visMakeMesh`:928 |
|
| 233 |
+
| 222 | `INT_VIS_DROP_MESH` | `visDropMesh`:929 |
|
| 234 |
+
| 223 | `INT_VIS_SET_TRANSFORMATION` | `visSetTransformation`:930 |
|
| 235 |
+
| 224 | `INT_VIS_SET_TRANSFORMATION_MAT` | `visSetTransformation`:931 |
|
| 236 |
+
| 225 | `INT_VIS_SET_DRAW_MODE` | `visSetDrawMode`:932 |
|
| 237 |
+
| 226 | `INT_VIS_SET_COLOR` | `visSetColor`:933 |
|
| 238 |
+
| 227 | `INT_VIS_SET_COLOR4` | `visSetColor`:934 |
|
| 239 |
+
| 228 | `INT_VIS_SET_POINT_SIZE` | `visSetPointSize`:935 |
|
| 240 |
+
| 229 | `INT_VIS_SET_LINE_WIDTH` | `visSetLineWidth`:936 |
|
| 241 |
+
| 230 | `INT_VIS_SET_SMOOTH` | `visSetSmooth`:937 |
|
| 242 |
+
| 231 | `INT_VIS_SET_BLEND` | `visSetBlend`:938 |
|
| 243 |
+
| 232 | `INT_VIS_SET_CULL` | `visSetCull`:939 |
|
| 244 |
+
| 233 | `INT_VIS_INIT_VERTEX_DATA` | `visInitVertexData`:940 |
|
| 245 |
+
| 234 | `INT_VIS_SET_FIRST_DISP_VERTEX` | `visSetFirstDispVertex`:941 |
|
| 246 |
+
| 235 | `INT_VIS_SET_DISP_VERTEX_COUNT` | `visSetDispVertexCount`:942 |
|
| 247 |
+
| 236 | `INT_VIS_LOAD_VERTEX_DATA` | `visLoadVertexData`:943 |
|
| 248 |
+
| 237 | `INT_VIS_LOAD_COLOR_DATA` | `visLoadColorData`:944 |
|
| 249 |
+
| 238 | `INT_VIS_LOAD_COLOR4_DATA` | `visLoadColorData`:945 |
|
| 250 |
+
| 239 | `INT_VIS_RELOAD_VERTEX_DATA_PART` | `visReloadVertexDataPart`:946 |
|
| 251 |
+
| 240 | `INT_VIS_RELOAD_COLOR_DATA_PART` | `visReloadColorDataPart`:947 |
|
| 252 |
+
| 241 | `INT_VIS_RELOAD_COLOR4_DATA_PART` | `visReloadColorDataPart`:948 |
|
| 253 |
+
| 242 | `INT_WRITE_TEXT_TO_CLIPBOARD` | `writeTextToClipboard`:949 |
|
| 254 |
+
| 243 | `INT_READ_TEXT_FROM_CLIPBOARD` | `readTextFromClipboard`:950, `readTextFromClipboard`:986 |
|
| 255 |
+
| 244 | `INT_SINGLE_FILE_OPEN_DIALOG` | `singleFileOpenDialog`:951 |
|
| 256 |
+
| 245 | `INT_SINGLE_FILE_SAVE_DIALOG` | `singleFileSaveDialog`:952 |
|
| 257 |
+
| 246 | `INT_CALL_PROGRAM` | `callProgram`:953 |
|
| 258 |
+
| 247 | `INT_START_PROGRAM` | `startProgram`:954 |
|
| 259 |
+
| 248 | `INT_CLOSE_APPLICATION` | `closeApplication`:955 |
|
| 260 |
+
|
| 261 |
+
## Core-Grid.ixpl
|
| 262 |
+
|
| 263 |
+
Source: `data/sources/include/core/Core-Grid.ixpl`; SHA-256 `7a64e3d0e90b00ff6e6d821b7304baa624729b0548eb6a36d928eba23f574de1`.
|
| 264 |
+
|
| 265 |
+
| ID | Constant(s) | Wrapper(s), source lines |
|
| 266 |
+
| ---: | --- | --- |
|
| 267 |
+
| 249 | `INT_SET_GRID_ACTIVE` | `setGridActive`:183 |
|
| 268 |
+
| 250 | `INT_SET_GRID_AXIS_ALIGNMENT_BIAS` | `setGridAxisAlignmentBias`:184 |
|
| 269 |
+
| 251 | `INT_SET_GRID_AXIS_LINE_WIDTH` | `setGridAxisLineWidth`:185 |
|
| 270 |
+
| 252 | `INT_SET_GRID_AXIS_X` | `setGridAxisX`:186 |
|
| 271 |
+
| 253 | `INT_SET_GRID_AXIS_XN_COLOR` | `setGridAxisXNColor`:187 |
|
| 272 |
+
| 254 | `INT_SET_GRID_AXIS_XP_COLOR` | `setGridAxisXPColor`:188 |
|
| 273 |
+
| 255 | `INT_SET_GRID_AXIS_Y` | `setGridAxisY`:189 |
|
| 274 |
+
| 256 | `INT_SET_GRID_AXIS_YN_COLOR` | `setGridAxisYNColor`:190 |
|
| 275 |
+
| 257 | `INT_SET_GRID_AXIS_YP_COLOR` | `setGridAxisYPColor`:191 |
|
| 276 |
+
| 258 | `INT_SET_GRID_AXIS_Z` | `setGridAxisZ`:192 |
|
| 277 |
+
| 259 | `INT_SET_GRID_AXIS_ZN_COLOR` | `setGridAxisZNColor`:193 |
|
| 278 |
+
| 260 | `INT_SET_GRID_AXIS_ZP_COLOR` | `setGridAxisZPColor`:194 |
|
| 279 |
+
| 261 | `INT_SET_GRID_CELLS_PER_MAJOR_STEP` | `setGridCellsPerMajorStep`:195 |
|
| 280 |
+
| 262 | `INT_SET_GRID_CELLS_PER_MAJOR_STEP_AROUND` | `setGridCellsPerMajorStepAround`:196 |
|
| 281 |
+
| 263 | `INT_SET_GRID_CIRCLE_RESOLUTION` | `setGridCircleResolution`:197 |
|
| 282 |
+
| 264 | `INT_SET_GRID_CIRCLE_RESOLUTION_BASE` | `setGridCircleResolutionBase`:198 |
|
| 283 |
+
| 265 | `INT_SET_GRID_CURSOR_COLOR` | `setGridCursorColor`:199 |
|
| 284 |
+
| 266 | `INT_SET_GRID_CURSOR_LINE_WIDTH` | `setGridCursorLineWidth`:200 |
|
| 285 |
+
| 267 | `INT_SET_GRID_CURSOR_SNAP_TO_CENTER_LINES` | `setGridCursorSnapToCenterLines`:201 |
|
| 286 |
+
| 268 | `INT_SET_GRID_CURSOR_SNAP_TO_CIRCLES` | `setGridCursorSnapToCircles`:202 |
|
| 287 |
+
| 269 | `INT_SET_GRID_CURSOR_SNAP_TO_XYU` | `setGridCursorSnapToXYU`:203 |
|
| 288 |
+
| 270 | `INT_SET_GRID_CURSOR_SNAP_TO_XYV` | `setGridCursorSnapToXYV`:204 |
|
| 289 |
+
| 271 | `INT_SET_GRID_CURSOR_SNAP_TO_YZU` | `setGridCursorSnapToYZU`:205 |
|
| 290 |
+
| 272 | `INT_SET_GRID_CURSOR_SNAP_TO_YZV` | `setGridCursorSnapToYZV`:206 |
|
| 291 |
+
| 273 | `INT_SET_GRID_CURSOR_SNAP_TO_ZXU` | `setGridCursorSnapToZXU`:207 |
|
| 292 |
+
| 274 | `INT_SET_GRID_CURSOR_SNAP_TO_ZXV` | `setGridCursorSnapToZXV`:208 |
|
| 293 |
+
| 275 | `INT_SET_GRID_MAJOR_COLOR` | `setGridMajorColor`:209 |
|
| 294 |
+
| 276 | `INT_SET_GRID_MAJOR_COUNT_AROUND_AT_RES_0` | `setGridMajorCountAroundAtRes0`:210 |
|
| 295 |
+
| 277 | `INT_SET_GRID_MAJOR_COUNT_PER_SIDE_AT_RES_0` | `setGridMajorCountPerSideAtRes0`:211 |
|
| 296 |
+
| 278 | `INT_SET_GRID_MAJOR_LINE_WIDTH` | `setGridMajorLineWidth`:212 |
|
| 297 |
+
| 279 | `INT_SET_GRID_MINOR_COLOR` | `setGridMinorColor`:213 |
|
| 298 |
+
| 280 | `INT_SET_GRID_MINOR_LINE_WIDTH` | `setGridMinorLineWidth`:214 |
|
| 299 |
+
| 281 | `INT_SET_GRID_ORIGIN` | `setGridOrigin`:215 |
|
| 300 |
+
| 282 | `INT_SET_GRID_PLANAR_OFFSET` | `setGridPlanarOffset`:216 |
|
| 301 |
+
| 283 | `INT_SET_GRID_PLANE_SETUP` | `setGridPlaneSetup`:217 |
|
| 302 |
+
| 284 | `INT_SET_GRID_RESOLUTION` | `setGridResolution`:218 |
|
| 303 |
+
| 285 | `INT_SET_GRID_RESOLUTION_BASE` | `setGridResolutionBase`:219 |
|
| 304 |
+
| 286 | `INT_SET_GRID_SECONDARY_SNAP` | `setGridSecondarySnap`:220 |
|
| 305 |
+
| 287 | `INT_SET_GRID_SECONDARY_SNAP_RES` | `setGridSecondarySnapRes`:221 |
|
| 306 |
+
| 288 | `INT_SET_GRID_SECONDARY_SNAP_RES_BASE` | `setGridSecondarySnapResBase`:222 |
|
| 307 |
+
| 289 | `INT_SET_GRID_SHAPE` | `setGridShape`:223 |
|
| 308 |
+
| 290 | `INT_IS_GRID_ACTIVE` | `isGridActive`:224 |
|
| 309 |
+
| 291 | `INT_GET_GRID_AXIS_ALIGNMENT_BIAS` | `getGridAxisAlignmentBias`:225 |
|
| 310 |
+
| 292 | `INT_GET_GRID_AXIS_LINE_WIDTH` | `getGridAxisLineWidth`:226 |
|
| 311 |
+
| 293 | `INT_GET_GRID_AXIS_X` | `getGridAxisX`:227 |
|
| 312 |
+
| 294 | `INT_GET_GRID_AXIS_XN_COLOR` | `getGridAxisXNColor`:228 |
|
| 313 |
+
| 295 | `INT_GET_GRID_AXIS_XP_COLOR` | `getGridAxisXPColor`:229 |
|
| 314 |
+
| 296 | `INT_GET_GRID_AXIS_Y` | `getGridAxisY`:230 |
|
| 315 |
+
| 297 | `INT_GET_GRID_AXIS_YN_COLOR` | `getGridAxisYNColor`:231 |
|
| 316 |
+
| 298 | `INT_GET_GRID_AXIS_YP_COLOR` | `getGridAxisYPColor`:232 |
|
| 317 |
+
| 299 | `INT_GET_GRID_AXIS_Z` | `getGridAxisZ`:233 |
|
| 318 |
+
| 300 | `INT_GET_GRID_AXIS_ZN_COLOR` | `getGridAxisZNColor`:234 |
|
| 319 |
+
| 301 | `INT_GET_GRID_AXIS_ZP_COLOR` | `getGridAxisZPColor`:235 |
|
| 320 |
+
| 302 | `INT_GET_GRID_CELLS_PER_MAJOR_STEP` | `getGridCellsPerMajorStep`:236 |
|
| 321 |
+
| 303 | `INT_GET_GRID_CELLS_PER_MAJOR_STEP_AROUND` | `getGridCellsPerMajorStepAround`:237 |
|
| 322 |
+
| 304 | `INT_GET_GRID_CIRCLE_RESOLUTION` | `getGridCircleResolution`:238 |
|
| 323 |
+
| 305 | `INT_GET_GRID_CIRCLE_RESOLUTION_BASE` | `getGridCircleResolutionBase`:239 |
|
| 324 |
+
| 306 | `INT_GET_GRID_CURSOR_COLOR` | `getGridCursorColor`:240 |
|
| 325 |
+
| 307 | `INT_GET_GRID_CURSOR_LINE_WIDTH` | `getGridCursorLineWidth`:241 |
|
| 326 |
+
| 308 | `INT_GET_GRID_CURSOR_PLANE` | `getGridCursorPlane`:242 |
|
| 327 |
+
| 309 | `INT_GET_GRID_CURSOR_POSITION` | `getGridCursorPosition`:243 |
|
| 328 |
+
| 310 | `INT_IS_GRID_CURSOR_PRESENT` | `isGridCursorPresent`:244 |
|
| 329 |
+
| 311 | `INT_DOES_GRID_CURSOR_SNAP_TO_CENTER_LINES` | `doesGridCursorSnapToCenterLines`:245 |
|
| 330 |
+
| 312 | `INT_DOES_GRID_CURSOR_SNAP_TO_CIRCLES` | `doesGridCursorSnapToCircles`:246 |
|
| 331 |
+
| 313 | `INT_DOES_GRID_CURSOR_SNAP_TO_XYU` | `doesGridCursorSnapToXYU`:247 |
|
| 332 |
+
| 314 | `INT_DOES_GRID_CURSOR_SNAP_TO_XYV` | `doesGridCursorSnapToXYV`:248 |
|
| 333 |
+
| 315 | `INT_DOES_GRID_CURSOR_SNAP_TO_YZU` | `doesGridCursorSnapToYZU`:249 |
|
| 334 |
+
| 316 | `INT_DOES_GRID_CURSOR_SNAP_TO_YZV` | `doesGridCursorSnapToYZV`:250 |
|
| 335 |
+
| 317 | `INT_DOES_GRID_CURSOR_SNAP_TO_ZXU` | `doesGridCursorSnapToZXU`:251 |
|
| 336 |
+
| 318 | `INT_DOES_GRID_CURSOR_SNAP_TO_ZXV` | `doesGridCursorSnapToZXV`:252 |
|
| 337 |
+
| 319 | `INT_GET_GRID_MAJOR_COLOR` | `getGridMajorColor`:253 |
|
| 338 |
+
| 320 | `INT_GET_GRID_MAJOR_COUNT_AROUND_AT_RES_0` | `getGridMajorCountAroundAtRes0`:254 |
|
| 339 |
+
| 321 | `INT_GET_GRID_MAJOR_COUNT_PER_SIDE_AT_RES_0` | `getGridMajorCountPerSideAtRes0`:255 |
|
| 340 |
+
| 322 | `INT_GET_GRID_MAJOR_LINE_WIDTH` | `getGridMajorLineWidth`:256 |
|
| 341 |
+
| 323 | `INT_GET_GRID_MINOR_COLOR` | `getGridMinorColor`:257 |
|
| 342 |
+
| 324 | `INT_GET_GRID_MINOR_LINE_WIDTH` | `getGridMinorLineWidth`:258 |
|
| 343 |
+
| 325 | `INT_GET_GRID_ORIGIN` | `getGridOrigin`:259 |
|
| 344 |
+
| 326 | `INT_GET_GRID_PLANAR_OFFSET` | `getGridPlanarOffset`:260 |
|
| 345 |
+
| 327 | `INT_GET_GRID_PLANE_SETUP` | `getGridPlaneSetup`:261 |
|
| 346 |
+
| 328 | `INT_GET_GRID_RESOLUTION` | `getGridResolution`:262 |
|
| 347 |
+
| 329 | `INT_GET_GRID_RESOLUTION_BASE` | `getGridResolutionBase`:263 |
|
| 348 |
+
| 330 | `INT_GRID_USES_SECONDARY_SNAP` | `gridUsesSecondarySnap`:264 |
|
| 349 |
+
| 331 | `INT_GET_GRID_SECONDARY_SNAP_RES` | `getGridSecondarySnapRes`:265 |
|
| 350 |
+
| 332 | `INT_GET_GRID_SECONDARY_SNAP_RES_BASE` | `getGridSecondarySnapResBase`:266 |
|
| 351 |
+
| 333 | `INT_GET_GRID_SHAPE` | `getGridShape`:267 |
|
| 352 |
+
|
| 353 |
+
## Core-Mb3.ixpl
|
| 354 |
+
|
| 355 |
+
Source: `data/sources/include/core/Core-Mb3.ixpl`; SHA-256 `0cac47e8a8f31504d2db7739a1e8e2af657c507a4a3de6f4ac786ca6150e4b65`.
|
| 356 |
+
|
| 357 |
+
| ID | Constant(s) | Wrapper(s), source lines |
|
| 358 |
+
| ---: | --- | --- |
|
| 359 |
+
| 405 | `INT_NEW_WORLD` | `newWorld`:19 |
|
| 360 |
+
| 406 | `INT_SET_RENDER_SETTINGS` | `setRenderSettings`:20 |
|
| 361 |
+
| 407 | `INT_GET_RENDER_SETTINGS` | `getRenderSettings`:21 |
|
| 362 |
+
|
| 363 |
+
## Core-QuakeWorld.ixpl
|
| 364 |
+
|
| 365 |
+
Source: `data/sources/include/core/Core-QuakeWorld.ixpl`; SHA-256 `52f80d4535ed61690105520560d6d8356a5ab529eebb1baf7eb6f0e6defd988c`.
|
| 366 |
+
|
| 367 |
+
| ID | Constant(s) | Wrapper(s), source lines |
|
| 368 |
+
| ---: | --- | --- |
|
| 369 |
+
| 334 | `INT_ADD_BRUSH` | `addBrush`:192 |
|
| 370 |
+
| 335 | `INT_ADD_PATCH_9` | `addPatch9`:193 |
|
| 371 |
+
| 336 | `INT_PREPARE_STRING_PROPERTY` | `prepareStringProperty`:194 |
|
| 372 |
+
| 337 | `INT_DROP_STRING_PROPERTY` | `dropStringProperty`:195 |
|
| 373 |
+
| 338 | `INT_PREPARE_UV_PROPERTY` | `prepareUVProperty`:196 |
|
| 374 |
+
| 339 | `INT_DROP_UV_PROPERTY` | `dropUVProperty`:197 |
|
| 375 |
+
| 340 | `INT_SELECT_ALL` | `selectAll`:198 |
|
| 376 |
+
| 341 | `INT_SELECT_BRUSH` | `selectBrush`:199 |
|
| 377 |
+
| 342 | `INT_SELECT_WITH_RAY` | `selectWithRay`:200 |
|
| 378 |
+
| 343 | `INT_INTERSECT_WITH_RAY` | `intersectWithRay`:201 |
|
| 379 |
+
| 344 | `INT_SELECT_INSIDE_OF_ANY_SELECTED_AABB` | `selectInsideOfAnySelectedAABB`:202 |
|
| 380 |
+
| 345 | `INT_SELECT_TOUCHING_ANY_SELECTED_AABB` | `selectTouchingAnySelectedAABB`:203 |
|
| 381 |
+
| 346 | `INT_SELECT_INSIDE_OF_ANY_SELECTED_BRUSH` | `selectInsideOfAnySelectedBrush`:204 |
|
| 382 |
+
| 347 | `INT_SELECT_TOUCHING_ANY_SELECTED_BRUSH` | `selectTouchingAnySelectedBrush`:205 |
|
| 383 |
+
| 348 | `INT_HIDE_SELECTED` | `hideSelected`:206 |
|
| 384 |
+
| 349 | `INT_SHOW_HIDDEN` | `showHidden`:207 |
|
| 385 |
+
| 350 | `INT_GET_TOTAL_BRUSH_COUNT` | `getTotalBrushCount`:208 |
|
| 386 |
+
| 351 | `INT_GET_SELECTED_BRUSH_COUNT` | `getSelectedBrushCount`:209 |
|
| 387 |
+
| 352 | `INT_GET_HIDDEN_BRUSH_COUNT` | `getHiddenBrushCount`:210 |
|
| 388 |
+
| 353 | `INT_DESELECT` | `deselect`:211 |
|
| 389 |
+
| 354 | `INT_READ_SELECTED_BRUSH_PLANES` | `readSelectedBrushPlanes`:212, `readSelectedBrushPlanes`:264 |
|
| 390 |
+
| 355 | `INT_REWRITE_SELECTED_BRUSH_PLANES` | `rewriteSelectedBrushPlanes`:213 |
|
| 391 |
+
| 356 | `INT_ADD_PLANES_TO_SELECTED_BRUSH` | `addPlanesToSelectedBrush`:214 |
|
| 392 |
+
| 357 | `INT_ADD_PLANES_TO_SELECTED_BRUSHES` | `addPlanesToSelectedBrushes`:215 |
|
| 393 |
+
| 358 | `INT_READ_SELECTED_BRUSH_PLANE` | `readSelectedBrushPlane`:216, `readSelectedBrushPlane`:265 |
|
| 394 |
+
| 359 | `INT_REWRITE_SELECTED_BRUSH_PLANE` | `rewriteSelectedBrushPlane`:217 |
|
| 395 |
+
| 360 | `INT_READ_STRINGS_FROM_SEL_BRUSH_PLANES` | `readStringsFromSelBrushPlanes`:218, `readStringsFromSelBrushPlanes`:266 |
|
| 396 |
+
| 361 | `INT_WRITE_STRINGS_FOR_SEL_BRUSH_PLANES` | `writeStringsForSelBrushPlanes`:219 |
|
| 397 |
+
| 362 | `INT_READ_STRING_FROM_SEL_BRUSH_PLANE` | `readStringFromSelBrushPlane`:220, `readStringFromSelBrushPlane`:267 |
|
| 398 |
+
| 363 | `INT_WRITE_STRING_FOR_SEL_BRUSH_PLANE` | `writeStringForSelBrushPlane`:221 |
|
| 399 |
+
| 364 | `INT_READ_UVS_FROM_SEL_BRUSH_PLANES` | `readUVsFromSelBrushPlanes`:222, `readUVsFromSelBrushPlanes`:268 |
|
| 400 |
+
| 365 | `INT_WRITE_UVS_FOR_SEL_BRUSH_PLANES` | `writeUVsForSelBrushPlanes`:223 |
|
| 401 |
+
| 366 | `INT_READ_UV_FROM_SEL_BRUSH_PLANE` | `readUVFromSelBrushPlane`:224, `readUVFromSelBrushPlane`:269 |
|
| 402 |
+
| 367 | `INT_WRITE_UV_FOR_SEL_BRUSH_PLANE` | `writeUVForSelBrushPlane`:225 |
|
| 403 |
+
| 368 | `INT_DELETE_PLANE_FROM_SELECTED_BRUSH` | `deletePlaneFromSelectedBrush`:226 |
|
| 404 |
+
| 369 | `INT_DELETE_SELECTED` | `deleteSelected`:227 |
|
| 405 |
+
| 370 | `INT_DELETE_SELECTED_BRUSH` | `deleteSelectedBrush`:228 |
|
| 406 |
+
| 371 | `INT_DELETE_HIDDEN_BRUSH` | `deleteHiddenBrush`:229 |
|
| 407 |
+
| 372 | `INT_FETCH_BRUSH_PLANE_CONTOURS` | `fetchBrushPlaneContours`:230, `fetchBrushPlaneContours`:270 |
|
| 408 |
+
| 373 | `INT_FETCH_BRUSH_PLANE_CONTOUR` | `fetchBrushPlaneContour`:231, `fetchBrushPlaneContour`:271 |
|
| 409 |
+
| 374 | `INT_IS_POINT_OBSTRUCTED` | `isPointObstructed`:232 |
|
| 410 |
+
| 375 | `INT_MERGE_SELECTIONS` | `mergeSelections`:233 |
|
| 411 |
+
| 376 | `INT_INTERSECT_SELECTED_BRUSHES` | `intersectSelectedBrushes`:234 |
|
| 412 |
+
| 377 | `INT_MERGE_SELECTED_BRUSHES` | `mergeSelectedBrushes`:235 |
|
| 413 |
+
| 378 | `INT_TRANSFORM_SELECTED` | `transformSelected`:236 |
|
| 414 |
+
| 379 | `INT_CLONE_SELECTED_WITH_TRANSFORMATION` | `cloneSelected`:237 |
|
| 415 |
+
| 380 | `INT_CLONE_SELECTED_WITH_EXTRA_PLANES` | `cloneSelected`:238 |
|
| 416 |
+
| 381 | `INT_TRANSFORM_BRUSH_PLANES_P` | `transformBrushPlanes`:239 |
|
| 417 |
+
| 382 | `INT_TRANSFORM_BRUSH_PLANES_A` | `transformBrushPlanes`:240 |
|
| 418 |
+
| 383 | `INT_SPAN_SELECTED` | `spanSelected`:241, `spanSelected`:272 |
|
| 419 |
+
| 384 | `INT_SPAN_SELECTED_BRUSH` | `spanSelectedBrush`:242, `spanSelectedBrush`:273 |
|
| 420 |
+
| 385 | `INT_NEW_UNDO_STEP` | `newUndoStep`:243 |
|
| 421 |
+
| 386 | `INT_END_UNDO_STEP` | `endUndoStep`:244 |
|
| 422 |
+
| 387 | `INT_CLEAR_UNDO_STEPS` | `clearUndoSteps`:245 |
|
| 423 |
+
| 388 | `INT_UNDO` | `undo`:246 |
|
| 424 |
+
| 389 | `INT_REDO` | `redo`:247 |
|
| 425 |
+
| 390 | `INT_SET_RENDER_MATERIAL` | `setRenderMaterial`:248 |
|
| 426 |
+
| 391 | `INT_CLEAR_RENDER_MATERIAL` | `clearRenderMaterial`:249 |
|
| 427 |
+
| 392 | `INT_SAVE_WORLD_TO_FILE` | `saveWorldToFile`:250 |
|
| 428 |
+
| 393 | `INT_LOAD_WORLD_FROM_FILE` | `loadWorldFromFile`:251 |
|
| 429 |
+
| 394 | `INT_SET_MAX_UNDO_STEP_COUNT` | `setMaxUndoStepCount`:252 |
|
| 430 |
+
| 395 | `INT_GET_MAX_UNDO_STEP_COUNT` | `getMaxUndoStepCount`:253 |
|
| 431 |
+
| 396 | `INT_SET_BRUSH_SPATIAL_BALANCING_COUNTS` | `setBrushSpatialBalancingCounts`:254 |
|
| 432 |
+
| 397 | `INT_SET_RENDER_DATA_CACHE_LEVEL` | `setRenderDataCacheLevel`:255 |
|
| 433 |
+
| 398 | `INT_SET_RENDER_DISTANCE` | `setRenderDistance`:256 |
|
| 434 |
+
| 399 | `INT_SET_RENDER_INTERVAL` | `setRenderInterval`:257 |
|
| 435 |
+
| 400 | `INT_GET_BRUSH_SPATIAL_BALANCING_COUNTS` | `getBrushSpatialBalancingCounts`:258 |
|
| 436 |
+
| 401 | `INT_GET_RENDER_DATA_CACHE_LEVEL` | `getRenderDataCacheLevel`:259 |
|
| 437 |
+
| 402 | `INT_GET_RENDER_DISTANCE` | `getRenderDistance`:260 |
|
| 438 |
+
| 403 | `INT_GET_RENDER_INTERVAL` | `getRenderInterval`:261 |
|
| 439 |
+
| 404 | `INT_RENDER_NOW` | `renderNow`:262 |
|
docs/DEPENDENCIES.md
ADDED
|
@@ -0,0 +1,83 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Dependency and build map
|
| 2 |
+
|
| 3 |
+
Source-level finding F22, 2026-10-21. Baseline paths are relative to `assets/references/extracted/2016-03-10-c/`. All five builds are indexed in [source-map.json](../assets/analysis/source-map.json); source hashes and line anchors accompany each edge.
|
| 4 |
+
|
| 5 |
+
## Compile-time include graph
|
| 6 |
+
|
| 7 |
+
`tools/includePaths.txt` declares five search directories relative to tools: `data/sources/include/core`, `include/IXPL`, `include/IXPL/general`, `include/IXPL/files`, and `include`. The index additionally considers a source-local file candidate. Actual compiler search precedence is unmeasured.
|
| 8 |
+
|
| 9 |
+
| Build | IXPL files | Include directives | Missing or ambiguous candidate sets |
|
| 10 |
+
| --- | ---: | ---: | ---: |
|
| 11 |
+
| 2015-10-03 | 42 | 91 | 0 |
|
| 12 |
+
| 2015-11-15 | 42 | 91 | 0 |
|
| 13 |
+
| 2015-11-24 | 42 | 91 | 0 |
|
| 14 |
+
| 2015-12-08 | 43 | 96 | 0 |
|
| 15 |
+
| 2016-03-10-c | 47 | 118 | 0 |
|
| 16 |
+
|
| 17 |
+
Every directive has exactly one existing candidate in this corpus. This establishes source closure under the stated candidate policy, not successful compilation. The index retains direct/transitive include edges and plugin-qualified Core method references; virtual calls, branches and dynamic handler invocations are not a typed execution graph.
|
| 18 |
+
|
| 19 |
+
## Build and execution boundaries
|
| 20 |
+
|
| 21 |
+
```mermaid
|
| 22 |
+
flowchart TD
|
| 23 |
+
Start[First-start BAT] --> ModelBuild[IXPL cxo model build]
|
| 24 |
+
Start --> PluginBuild[IXPL cso plugin build]
|
| 25 |
+
ModelBuild --> IXM[Generated models/ixm]
|
| 26 |
+
PluginBuild --> Plugin[Generated plugins/plugin]
|
| 27 |
+
Editor[Native editor / Akula host] --> Plugin
|
| 28 |
+
Editor --> IXM
|
| 29 |
+
Plugin --> API[Core interrupt APIs]
|
| 30 |
+
Plugin --> Tasks[Named task interfaces]
|
| 31 |
+
Menu[Main-menu plugin] --> Batch[Conversion BAT wrappers]
|
| 32 |
+
Batch --> Converter[Managed file-formats tool]
|
| 33 |
+
Converter --> DAT[MB3 DAT intermediates]
|
| 34 |
+
Editor --> DAT
|
| 35 |
+
```
|
| 36 |
+
|
| 37 |
+
Arrows represent source/build dependencies, not a measured temporal load order.
|
| 38 |
+
|
| 39 |
+
The first-start script compiles top-level model and plugin sources before moving the editor executable to the archive root. Model BAT wrappers use `IXPL.exe cxo <source> <output.ixm>`; plugin wrappers use `cso <source> <output.plugin>`. Top-level `build all.bat` enumerates only `*.ixpl` in its current directory; experimental sources in `extra stuff/` require manual promotion. The runtime plugin enumeration and exact ordering are still host implementation questions.
|
| 40 |
+
|
| 41 |
+
GPU configuration BAT files only switch the presence of root `ATI.ix-workaround-marker` / `NVIDIA.ix-workaround-marker`; they do not themselves run a graphics probe or modify shader source. The cache-clear BAT deletes `data/shaders/*.cache`. Sources: the two configure scripts and `clear shader cache.bat`, all lines 1–3.
|
| 42 |
+
|
| 43 |
+
The three EXEs are separately inventoried native-editor/managed-tool artifacts, as recorded in F03. This pass does not identify PE imports, CLR target versions, external DLL resolution or executable resource tables. The historical Wine/.NET recipe remains reported evidence.
|
| 44 |
+
|
| 45 |
+
## File/resource edge classification
|
| 46 |
+
|
| 47 |
+
The machine index records a literal expression and same-name archive candidates for config/text/texture/process/world-file calls. It keeps dynamically computed names unresolved. Same-name matches are candidate dependencies, not proof of host path resolution.
|
| 48 |
+
|
| 49 |
+
| Resource family | Observation | Disposition |
|
| 50 |
+
| --- | --- | --- |
|
| 51 |
+
| Plugin settings | Most literal CFG names have bundled settings files | Map consumer rules and generated saves before porting |
|
| 52 |
+
| `main menu.cfg` | Requested by `main menu.ixpl:261,301`, absent in the latest archive | Optional/generated settings candidate; loader declaration says missing config is silent, not automatically a startup failure |
|
| 53 |
+
| Three icon atlases | Calls request names without the shipped `56` suffix | Loader naming rule unresolved; retain both requested and shipped names |
|
| 54 |
+
| `conversion.log`, `load.mb3dat`, `save.mb3dat` | Absent as archive members but created/used by conversion workflows | Expected generated intermediates, not missing distribution downloads |
|
| 55 |
+
| `content textures/index.cfg` | Named by root MB3 config but absent | External/optional content dependency; effect unknown |
|
| 56 |
+
| SIL font notice | ReadMe names a file absent from every ZIP | Unresolved provenance/redistribution requirement |
|
| 57 |
+
| Compiled plugins/models/shader caches | No regular compiled plugin/model samples bundled | Generated build/runtime products; keep separate from immutable sources |
|
| 58 |
+
|
| 59 |
+
The source map does not classify every literal as a resource. Translation keys, tool names and help text are separate domains. It also does not treat a missing exact-name candidate as proof of an error.
|
| 60 |
+
|
| 61 |
+
## Version differences
|
| 62 |
+
|
| 63 |
+
Adjacent builds change as follows (regular paths; byte hashes):
|
| 64 |
+
|
| 65 |
+
| Transition | Added | Removed | Changed same-path files |
|
| 66 |
+
| --- | ---: | ---: | ---: |
|
| 67 |
+
| October 3 → November 15 | 0 | 1 | 8 |
|
| 68 |
+
| November 15 → November 24 | 1 | 0 | 8 |
|
| 69 |
+
| November 24 → December 8 | 1 | 0 | 24 |
|
| 70 |
+
| December 8 → March 10-c | 21 | 7 | 72 |
|
| 71 |
+
|
| 72 |
+
No adjacent transition has an identical-byte removed-to-added rename candidate. The latest has several identical-copy candidates for minimal `main.shown=false` settings, which do not imply a shared implementation or semantic equivalence. The older `Mb3 tools` and base-window modules change names/content and need semantic comparison. The report records hash identity separately from same-basename candidates.
|
| 73 |
+
|
| 74 |
+
## Native rewrite dependency cuts
|
| 75 |
+
|
| 76 |
+
1. Specify Core/world/grid semantics independently of Akula's original execution engine.
|
| 77 |
+
2. Replace BAT/process conversion with native codecs and isolated CLI tools.
|
| 78 |
+
3. Replace cursor/model generation with deterministic native geometry after IXModel contracts are validated.
|
| 79 |
+
4. Port bundled plugin functionality into Rust modules/services; decide third-party IXPL compatibility separately.
|
| 80 |
+
5. Keep preferences, view state, document data, derived meshes and task messages distinct.
|
| 81 |
+
6. Validate missing-resource fallbacks and plugin service ordering before promoting source declarations to runtime contracts.
|
| 82 |
+
|
| 83 |
+
Next: P2.11 resource lookup semantics and semantic version diffs; P3.06 executable dependencies; P4.04/P4.05 lifecycle; P9 shader/asset integration. No target-native Rust implementation is introduced by this pass.
|
docs/FINDINGS.md
CHANGED
|
@@ -74,7 +74,7 @@ Grid references and strings describe rectangular/circular grids, origin and axis
|
|
| 74 |
|
| 75 |
## F08 — Formats and conversion boundary
|
| 76 |
|
| 77 |
-
|
| 78 |
|
| 79 |
The nine conversion BAT files connect MB3 DAT to four text formats in both directions, plus DAT-to-Wavefront OBJ. `main menu.ixpl` calls these scripts and loads/saves `load.mb3dat` / `save.mb3dat` intermediates. The converter command includes input type/path, output type/path, and conversion log path. Determine exact errors, numeric formatting, concurrency, and filesystem behavior later.
|
| 80 |
|
|
@@ -133,3 +133,19 @@ The [upstream macOS issue #26131](https://github.com/bevyengine/bevy/issues/2613
|
|
| 133 |
## F14 — Confirmed single-repository precedent
|
| 134 |
|
| 135 |
`urban-terror-rs/.gitattributes` selects `urt-code` by default and LFS for `assets/**`; its local config registers git-xet and its tracked asset objects are LFS pointers. Unlike glade, this is an active mixed repository. The user selected this pattern for Nanobrush, including every directory named `references/`. No separate dataset/asset branch/asset lockfile is used.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 74 |
|
| 75 |
## F08 — Formats and conversion boundary
|
| 76 |
|
| 77 |
+
Seven included grammars describe MB3 TXT, HL1 MAP, HL2 VMF, Q3 MAP, configuration, key configuration and IXPL. A separate text-markup demo illustrates display markup. MB3 TXT declares a world with computed-features flag, optional named string/UV property lists, brushes, per-plane properties and optional polygons, and Patch9 anchors plus optional points/normals.
|
| 78 |
|
| 79 |
The nine conversion BAT files connect MB3 DAT to four text formats in both directions, plus DAT-to-Wavefront OBJ. `main menu.ixpl` calls these scripts and loads/saves `load.mb3dat` / `save.mb3dat` intermediates. The converter command includes input type/path, output type/path, and conversion log path. Determine exact errors, numeric formatting, concurrency, and filesystem behavior later.
|
| 80 |
|
|
|
|
| 133 |
## F14 — Confirmed single-repository precedent
|
| 134 |
|
| 135 |
`urban-terror-rs/.gitattributes` selects `urt-code` by default and LFS for `assets/**`; its local config registers git-xet and its tracked asset objects are LFS pointers. Unlike glade, this is an active mixed repository. The user selected this pattern for Nanobrush, including every directory named `references/`. No separate dataset/asset branch/asset lockfile is used.
|
| 136 |
+
|
| 137 |
+
## F15–F20 — Format and shader source map
|
| 138 |
+
|
| 139 |
+
The [format report](FORMATS.md) separates MB3 TXT/DAT, map dialects, OBJ export, IXModel, plugin artifacts, configuration and shader containers. It records actual grammar constraints, the `I10MODEL` writer/version/opcodes, two writer inconsistencies, config/keymap consumer differences, selection visual patterns, and the patch shader's unused lighting calculation. These findings are observed source evidence; no codec round trip or visible behavior is yet verified.
|
| 140 |
+
|
| 141 |
+
## F21 — Core endpoint enumeration
|
| 142 |
+
|
| 143 |
+
The [host API map](HOST_APIS.md) resolves 408 latest Core IDs and all 448 wrapper sites, with a complete [ID-to-wrapper index](API_INDEX.md). The declaration set grows from 382 to 408 IDs across recovered builds. File I/O's overlapping 0–24 IDs remain a separate interface. Lifecycle, state, task buffers, declared preconditions and versioning boundaries are documented without assuming runtime ownership or dispatch behavior.
|
| 144 |
+
|
| 145 |
+
## F22 — Dependency closure and evolution
|
| 146 |
+
|
| 147 |
+
The [dependency map](DEPENDENCIES.md) records all 487 include directives across the five builds, their single existing candidates, direct/transitive source edges, literal/dynamic resource candidates, conversion/build processes and byte-level version differences. Missing generated intermediates are distinguished from absent exact-name resources. Actual compiler precedence, plugin loader ordering and executable dependencies remain open.
|
| 148 |
+
|
| 149 |
+
## F23 — Plugin/service map
|
| 150 |
+
|
| 151 |
+
The [plugin map](PLUGINS.md) accounts for 17 top-level plugins, five experimental sources and nine task clients. It indexes 201 tool registration call sites, identifies named service protocols, lifecycle callbacks, the raycast selection-mutation sequence, cached failed interface lookups, and single mutable callback slots. This establishes source relationships, not live execution traces or complete interaction parity.
|
docs/FORMATS.md
ADDED
|
@@ -0,0 +1,82 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Format map: source evidence
|
| 2 |
+
|
| 3 |
+
Observed 2026-10-21. Baseline archive: `Microbrush-3-wip-2016-03-10-c.zip`, SHA-256 `f972035324c1ede7e66771c398c035b9a355b569f68ddc30fdc4ed4ed0973982`. Paths and line numbers below are relative to `assets/references/extracted/2016-03-10-c/`. Full member hashes are in the [static source map](../assets/analysis/source-map.json) and [member inventory](REFERENCE_INVENTORY.md). These are grammar/writer observations, not runtime format conformance results.
|
| 4 |
+
|
| 5 |
+
## F15 — Separate the format layers
|
| 6 |
+
|
| 7 |
+
| Layer | Evidence | Current knowledge |
|
| 8 |
+
| --- | --- | --- |
|
| 9 |
+
| Editable world text | `data/reference/Mb3 TXT grammar.txt` | Explicit world/brush/plane/Patch9 syntax; conversion semantics still unknown |
|
| 10 |
+
| Editable world binary | `saveWorldToFile` / `loadWorldFromFile`, conversion BAT files | MB3 DAT boundary and command directions are visible; byte layout is unknown |
|
| 11 |
+
| Imported map formats | HL1 MAP, HL2 VMF, Q3 MAP grammars | Accepted syntax is described; semantic preservation is limited |
|
| 12 |
+
| Export mesh | DAT-to-`wfobj` BAT file | Export-only route is shipped; serialization details are unknown |
|
| 13 |
+
| Procedural model | `IXModel.ixpl` + `grid cursor.ixpl` | Source writer and opcode catalogue; different from MB3 DAT |
|
| 14 |
+
| Compiled plugin | `IXPL.exe cso` in build BAT files | Generated `.plugin` output; no compiled sample or layout recovered |
|
| 15 |
+
| Runtime config/localization | config and key-config grammars; CFG/TXT resources | Typed configuration plus a separate key-sequence language |
|
| 16 |
+
| Shader container | three `.shader` files | Stage-marked GLSL source with host-dependent uniforms/attributes |
|
| 17 |
+
|
| 18 |
+
The conversion CLI is structurally `Mb3 file formats.exe <input-type> <input-path> <output-type> <output-path> <log-path>`. Four text formats convert to `data/temp/load.mb3dat`; saves start from `data/temp/save.mb3dat`, with an additional `wfobj` export. File placement and CLI shape are observed in the BAT files. Argument validation, process exit behavior and concurrent conversion safety are not yet reproduced.
|
| 19 |
+
|
| 20 |
+
## F16 — MB3 TXT grammar
|
| 21 |
+
|
| 22 |
+
Source: `data/reference/Mb3 TXT grammar.txt:45–101`.
|
| 23 |
+
|
| 24 |
+
- `world(...)` starts with required `computedFeatures true|false`, then optional `stringProperties[...]`, optional `uvProperties[...]`, then zero or more brushes/patches. Their order is constrained by the grammar.
|
| 25 |
+
- `brush(...)` contains zero or more planes syntactically. The host API says invalid brushes are discarded; syntactic acceptance does not establish geometric validity.
|
| 26 |
+
- A `plane(...)` has three comma-separated three-component numeric tuples, repeated `s <index> <string>` entries, repeated `uv <index> (<five numbers>, <five numbers>)` entries, and an optional polygon vector list.
|
| 27 |
+
- Each UV five-tuple is documented as an axis vector plus scale and shift-before-scaling. The grammar does not specify index bounds, property lookup failure or duplicate property behavior.
|
| 28 |
+
- `patch9(...)` has four integers and an anchor vector list. If computed points are present, the normals list must also appear, in that order. The grammar imposes no anchor-list length consistency check.
|
| 29 |
+
- `Core-QuakeWorld.ixpl:17–21` separately requires odd anchor dimensions of at least three and at least two quads per tile per axis. These are API declaration constraints awaiting runtime verification.
|
| 30 |
+
- The grammar accepts signed integers/floats and exponent forms, ordinary escaped strings, line/block comments and whitespace. Numeric precision and printing are not established.
|
| 31 |
+
|
| 32 |
+
Do not silently interpret the plane's three serialized tuples as three points or as origin plus spanning vectors: the API declares `p0/u/v`, but the converter mapping has not been established. Selection sets, hidden state, undo history, view state and named worlds do not have explicit fields in this grammar. Their persistence behavior needs controlled save/load tests.
|
| 33 |
+
|
| 34 |
+
Next: P6.02/P6.03 single-feature fixtures and actual serializer observations; P5 numerical/geometry contracts.
|
| 35 |
+
|
| 36 |
+
## F17 — Imported dialects and loss boundary
|
| 37 |
+
|
| 38 |
+
| Grammar | Observed syntax | Limits to preserve in the specification |
|
| 39 |
+
| --- | --- | --- |
|
| 40 |
+
| HL1 MAP | Entities require one or more string key/value pairs; brush sides use three points, texture name, two bracketed four-number axes, then three numbers | This is the bracketed-axis style in the supplied grammar, not proof of every historical MAP dialect; no line-comment rule is listed |
|
| 41 |
+
| HL2 VMF | Lowercase/underscore block names; recursive key/value and block trees; world/entity/solid/side/hidden specializations plus generic `OtherStuff` | Recursive syntax can accept data which the converter later drops; quoted strings have no escape production here |
|
| 42 |
+
| Q3 MAP | Entity key/value pairs, plane brushes, and `patchDef2`; anchors contain five numbers; a plane side has texture name plus eight numbers | No `brushDef`/`brushDef3` specialization appears; dimensions and patch counts are not constrained by the grammar |
|
| 43 |
+
|
| 44 |
+
Sources: `HL1 MAP grammar.txt:30–58`, `HL2 VMF grammar.txt:23–91`, `Q3 MAP grammar.txt:32–83`.
|
| 45 |
+
|
| 46 |
+
`data/strings/English/main menu.txt` explicitly warns that unsupported features, including textures and entities, are dropped on import/save. Therefore grammar recognition is not a preservation guarantee. Native converters need a supported-subset/loss report, and original files must remain separate from rewritten output.
|
| 47 |
+
|
| 48 |
+
The Wavefront route is export only in the shipped menu and BAT scripts. Material/UV/index/group choices cannot be reconstructed from the BAT wrapper alone. No sample MAP/VMF/OBJ/MB3 file is in this recovered corpus.
|
| 49 |
+
|
| 50 |
+
## F18 — IXModel writer contract and anomalies
|
| 51 |
+
|
| 52 |
+
Source: `data/sources/include/IXPL/files/IXModel.ixpl`.
|
| 53 |
+
|
| 54 |
+
- `writeHeader:65–70` sends literal `I10MODEL` to `File::writeBytes`, sends integer `20160119`, and resets the next object ID to zero.
|
| 55 |
+
- `writeStrings:76–84` writes string count, then each string length and bytes. Whether string length counts bytes/code units is a runtime question.
|
| 56 |
+
- `CMD_*:93–185` declares 92 opcodes, numbered 0–91: node creation, graph/mesh references, attribute/index data, drawing/render state, custom data, animation, waits, and transforms.
|
| 57 |
+
- Constructors allocate implicit IDs using `next++`. Mesh loading writes target mesh, counts, and data through `File` primitives. `writeShorts:57–62` explicitly emits low then high bytes; this confirms the writer's 16-bit byte order only. It does not prove the host primitive width/endianness for every integer/float.
|
| 58 |
+
- `File.ixpl:59–70` writes a vec3 as three float operations in x/y/z order. The `File` interrupt namespace is distinct from the Core plugin namespace; do not merge their overlapping numeric IDs.
|
| 59 |
+
- Older four builds write version `20111101` and declare 90 opcodes (0–89). The latest uses version `20160119` and 92 opcodes. A decoder needs version-specific tables, not one guessed layout.
|
| 60 |
+
|
| 61 |
+
Two source inconsistencies need targeted investigation before calling the writer authoritative:
|
| 62 |
+
|
| 63 |
+
1. Many `reset*` functions accept `nodeOrMesh` but emit only the reset opcode, unlike their `set*` counterparts (`230–261`). The reader may have implicit targeting, or the writer may be incomplete. Do not invent a serialized target field.
|
| 64 |
+
2. `popFile:91` assigns `file` to the last stack entry before erasing that same entry. With nested pushes it appears to retain the popped handle rather than restore the previous handle. The single cursor generator does not demonstrate this case.
|
| 65 |
+
|
| 66 |
+
The cursor generator creates a line mesh from eight positions at ±0.5 through `IXModel`. This supplies a small native replacement target once the actual output contract is validated. No `.ixm` sample is bundled.
|
| 67 |
+
|
| 68 |
+
## F19 — Config and keymap languages
|
| 69 |
+
|
| 70 |
+
Source: `config file grammar.txt:4–6, 62–118`; `key config grammar.txt:58–91`.
|
| 71 |
+
|
| 72 |
+
The config contract explicitly says last entry wins unless a consumer treats repeated entries as an array, and a nested scope is equivalent to a dotted key. Types include bool, integer/long, float/double, strings, vector/color forms, and string tables. Ordinary and delimiter strings are distinct lexical forms. The text declares `KeyVec4` but the `Entry` alternatives include `KeyRGBA`, not a standalone `KeyVec4` branch: treat this as a grammar discrepancy until tested.
|
| 73 |
+
|
| 74 |
+
Do not apply last-wins globally. The task-priorities plugin collects repeated `task.name`/`task.priority` pairs in order and uses `indexOf`, giving the first matching name priority. This is a consumer-specific repeated-entry rule.
|
| 75 |
+
|
| 76 |
+
Keymaps bind comma-separated key sequences to named or numeric commands; leading minus unbinds. Unknown commands are documented as unbind operations. A terminal asterisk makes a binding nonmodal outside fly mode, with modifier combinations explicitly unsupported. Alt/control/shift modifier order is encoded as `a`, `c`, `s`. Normal operation and basic pass-through have different rules. This needs its own parser and interaction tests rather than translation to a flat shortcut dictionary.
|
| 77 |
+
|
| 78 |
+
## F20 — Shader container observations
|
| 79 |
+
|
| 80 |
+
`brushes.shader` and `patch9s.shader` have `@vertex330` and `@fragment330` sections and a std140 matrix block; `grid.shader` has the same stage names and many grid/camera/snap uniforms. Host binding, compilation defines and complete matrix conventions remain unknown.
|
| 81 |
+
|
| 82 |
+
`brushes.shader:92–106` uses face IDs 0/1/2/3 to distinguish unselected/main/set-1/set-2 visualization, including screen-space stripe patterns for auxiliary sets. `patch9s.shader:35–41` calculates a lighting value but writes the normal-color expression instead; translating the unused lighting expression as the visible shader would be incorrect. `brushes.shader:71–76` has a `WA_ATI` expression variant. Preserve observable output contracts separately from obsolete driver workarounds.
|
docs/HOST_APIS.md
ADDED
|
@@ -0,0 +1,64 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Host API map
|
| 2 |
+
|
| 3 |
+
Source-level finding F21, 2026-10-21. Baseline: build `2016-03-10-c`; full archive/member identities are in [the source map](../assets/analysis/source-map.json). The [API index](API_INDEX.md) enumerates all Core endpoints and their wrapper source lines. No executable, plugin or compiler was run.
|
| 4 |
+
|
| 5 |
+
## ABI composition
|
| 6 |
+
|
| 7 |
+
`data/sources/include/core/Core.ixpl:6–21` sets `coreVersion=2016031002`, includes Akula, and places each following API group immediately after the preceding group's end sentinel. `Akula.ixpl` declares `akulaCoreVersion=2016031000` and invokes the version check from a static block (`702–705`).
|
| 8 |
+
|
| 9 |
+
| Group | Declared interval | IDs | Interrupt wrapper sites |
|
| 10 |
+
| --- | --- | ---: | ---: |
|
| 11 |
+
| Akula | 0–248 | 249 | 279 |
|
| 12 |
+
| Grid | 249–333 | 85 | 85 |
|
| 13 |
+
| Quake world | 334–404 | 71 | 81 |
|
| 14 |
+
| MB3 | 405–407 | 3 | 3 |
|
| 15 |
+
| Total Core | 0–407 | 408 | 448 |
|
| 16 |
+
|
| 17 |
+
The extra wrappers are overloads/adapters sharing interrupt IDs. These intervals are fully resolved source expressions and contiguous, not a measured binary dispatch table. All latest Core interrupt sites have an enclosing indexed wrapper; signatures and raw interrupt arguments are retained in the machine report.
|
| 18 |
+
|
| 19 |
+
`File.ixpl` separately declares IDs 0–24 for create/open/close/size/read/write. These overlap the Core numbers and belong to a separate source interface. Their runtime dispatcher/compilation-context relationship is unverified.
|
| 20 |
+
|
| 21 |
+
## Contracts exposed by the declarations
|
| 22 |
+
|
| 23 |
+
| Area | Exposed operations | Evidence and rewrite implication |
|
| 24 |
+
| --- | --- | --- |
|
| 25 |
+
| Runtime/plugin | Version check, tool registration, load/finalize/view/camera callbacks | `Akula:357–365`; event callbacks are part of the host ABI, not just UI glue |
|
| 26 |
+
| Task messages | Five typed buffers and numeric priority | `Akula:369–374`; preserve message boundaries and ordering rules |
|
| 27 |
+
| UI/config/resources | Typed config, text I/O, dialogs, translation, font, texture and widgets | Many config settings are deferred; current/next getters differ (`350–355`) |
|
| 28 |
+
| Views/camera | Current view/world, cloning/closing, layout, fly/input, projection and camera transforms | View ownership is explicit; do not conflate a world with a viewport |
|
| 29 |
+
| Grid | Grid basis/origin/shape, snap settings, visual settings, current cursor/look-at state | `Core.ixpl:11` states these target the current view |
|
| 30 |
+
| World | Brush/patch creation, geometry/property/selection operations, undo, persistence and render caching | `Core.ixpl:15` targets the world in the current view |
|
| 31 |
+
| MB3 | New world, get/set per-view render settings | Three operations after the world API |
|
| 32 |
+
| Process/filesystem | Host call-program and file-dialog services; separate File utility ABI | Original conversion depends on process spawning; native codecs should replace this boundary |
|
| 33 |
+
|
| 34 |
+
The declarations use `&` for both inputs and returned objects. IXPL reference ownership/lifetime/aliasing is not yet specified; these signatures are not Rust lifetime designs.
|
| 35 |
+
|
| 36 |
+
### World semantics already explicit in source comments
|
| 37 |
+
|
| 38 |
+
`Core-QuakeWorld.ixpl:106–171` states that invalid brushes are collapsed/discarded, shown state is independent of selection, several selection operations accept only shown objects not already in a set, and ray queries ignore hidden objects. Inside/touching selection is based on AABBs or brush corners and is not a general exact overlap predicate. Hidden-brush bounds may be stale. An empty selection's bounds are all zero.
|
| 39 |
+
|
| 40 |
+
The same declarations specify 16-element transform matrices, clone transforms allowing an empty matrix, undo-step/redo clearing boundaries, undo limits that can be zero, spatial-balancing parameter constraints, and render cache levels 0/1/2. These are valuable explicit contracts, but numerical tolerances, topology, failures and actual runtime compliance remain open.
|
| 41 |
+
|
| 42 |
+
## Task execution and plugin-local services
|
| 43 |
+
|
| 44 |
+
`Akula.ixpl:369` documents hierarchical task queuing: the first task queued by an executing tool runs next; event-handler tasks are buffered; static blocks cannot queue tasks. This is not enough evidence to model the engine as a simple global FIFO.
|
| 45 |
+
|
| 46 |
+
Each task carries `int[]`, `long[]`, `float[]`, `double[]`, and `vec3[]`. Client helpers use integer discriminators plus tool IDs/handler indices, sometimes concatenate a string into an integer buffer, and use a named interface tool as an endpoint. Inspecting a task client's source reveals the protocol; executing it still depends on host scheduling and string conversion rules.
|
| 47 |
+
|
| 48 |
+
`tasks/camera.ixpl`, `grid.ixpl`, and `projections.ixpl` register callback indices and tags. `tasks/raycast.ixpl` keeps one mutable success callback, and `tasks/task priorities.ixpl` keeps one mutable query callback. Concurrent outstanding requests may overwrite these slots; this is a source risk to test, not a reproduced failure.
|
| 49 |
+
|
| 50 |
+
`getToolID` is documented to return -1 when absent. Task helpers initially use -2 for “not looked up yet” and cache the first lookup. Many do not retry after a missing service. Plugin availability/load timing therefore matters.
|
| 51 |
+
|
| 52 |
+
## API evolution
|
| 53 |
+
|
| 54 |
+
| Build | Resolved Core IDs | Maximum ID |
|
| 55 |
+
| --- | ---: | ---: |
|
| 56 |
+
| 2015-10-03 | 382 | 381 |
|
| 57 |
+
| 2015-11-15 | 382 | 381 |
|
| 58 |
+
| 2015-11-24 | 388 | 387 |
|
| 59 |
+
| 2015-12-08 | 390 | 389 |
|
| 60 |
+
| 2016-03-10-c | 408 | 407 |
|
| 61 |
+
|
| 62 |
+
The November 24 declaration set adds six undo-related names. December changes base-keymap operations. The latest adds property-table APIs, more render controls and additional lifecycle/undo operations. Some older names are replaced, so name additions alone do not explain endpoint-count changes. Group offsets shift; do not reuse current numeric IDs when interpreting older plugins.
|
| 63 |
+
|
| 64 |
+
Next: P4.03 preconditions/lifetimes/errors/callers for each endpoint; P4.04/P4.05 lifecycle/scheduling experiments; P3.14 host implementations when that investigation is undertaken. The table above closes source enumeration only.
|
docs/PLUGINS.md
ADDED
|
@@ -0,0 +1,70 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Plugin and task-service map
|
| 2 |
+
|
| 3 |
+
Source-level finding F23, 2026-10-21. Baseline is `2016-03-10-c`; member identities, includes, literal expressions, callback registrations and line anchors are in [source-map.json](../assets/analysis/source-map.json). [PLUGIN_INDEX.md](PLUGIN_INDEX.md) lists every observed `initTool` call site/name. These are static declarations and calls, not a measured runtime registration trace.
|
| 4 |
+
|
| 5 |
+
The latest distribution contains **17 top-level plugin sources**, **5 experimental sources**, **9 task-client includes**, **10 utility/misc includes**, **5 Core includes**, and **1 model generator**: 47 IXPL files in total. There are 201 `initTool` call sites in plugin/experimental sources, with conservatively resolved source names: 194 in top-level plugins and 7 in examples. They include service/internal tools; they are not 201 distinct user-facing commands or proof that all tools are active simultaneously.
|
| 6 |
+
|
| 7 |
+
## Top-level modules
|
| 8 |
+
|
| 9 |
+
| Plugin source basename | Responsibility visible in source | Main dependencies / port boundary |
|
| 10 |
+
| --- | --- | --- |
|
| 11 |
+
| `camera` | Camera controls, fly/navigation tools, camera panel and stopped notifications | Core camera/view services; Camera task clients |
|
| 12 |
+
| `grid` | Grid panel/settings/presets, cursor and update notifications | Core-Grid, raycast, camera and projection services |
|
| 13 |
+
| `projections` | Projection controls, saved memories and change notifications | Core view/projection services and task clients |
|
| 14 |
+
| `Mb3 main editing tools` | Main editing toolbox and modal operations | World/grid APIs, grid/camera/raycast/log helpers |
|
| 15 |
+
| `Mb3 render modes` | Six rendering mode selections, toolbar/view synchronization | MB3 per-view render settings and ViewEvents |
|
| 16 |
+
| `view layouts` | Six viewport layout presets and toolbar | View geometry/lifecycle APIs; shared-world views |
|
| 17 |
+
| `main menu` | New/load/save/export/world workflows, native dialogs and converter process calls | Core/WorldController/ViewEvents/Log and conversion BAT files |
|
| 18 |
+
| `world controller` | World registration, view clone/close policy and events | Core view lifecycle, task priorities, ViewEvents |
|
| 19 |
+
| `view events` | Fan-out of created/cloned/closing/closed notifications | Named task protocol; no rendered UI required |
|
| 20 |
+
| `raycast` | Raycast request/reply adapter returning position/normal | Core intersections and selected-brush plane access |
|
| 21 |
+
| `task priorities` | Ordered task-name/priority lookup | Config records and task buffers |
|
| 22 |
+
| `plugins menu` | Collect plugin menu entries and dispatch selected callbacks | PluginsMenu and TaskPriorities protocols |
|
| 23 |
+
| `Mb3 plugins` | Shortcut palette opening editing/render-mode toolbars and other panels | Named tools and plugin-menu registration |
|
| 24 |
+
| `GUI layout designer` | Interactive GUI construction/layout tooling | Widget APIs, config, log/help/menu utilities |
|
| 25 |
+
| `log` | Log registrations/messages and log UI | Core GUI, settings and typed task messages |
|
| 26 |
+
| `notes` | Notes window and settings/lifecycle behavior | GUI/config/log/plugin-menu helpers |
|
| 27 |
+
| `window controls` | Window interaction instructions/shortcuts | Core UI/window services |
|
| 28 |
+
|
| 29 |
+
The two plugin-menu/palette modules are not evidence of an implemented dynamic loader API. Actual `.plugin` discovery, load order, runtime isolation, unload behavior and error containment still belong to host investigation.
|
| 30 |
+
|
| 31 |
+
## Named task protocols
|
| 32 |
+
|
| 33 |
+
All nine client includes use a named `!interface` tool, a discriminant in `bufI`, and other typed buffers as needed. See `data/sources/include/tasks/` in the machine report.
|
| 34 |
+
|
| 35 |
+
| Endpoint | Client request / response shape | Source-level concern |
|
| 36 |
+
| --- | --- | --- |
|
| 37 |
+
| `camera.!interface` | Register client tool ID and handler index; return handler index | Fires when a continuous camera transformation stops, according to source comment |
|
| 38 |
+
| `grid.!interface` | Register client tool ID and handler index; return handler index | Grid cursor/look-at updates |
|
| 39 |
+
| `projections.!interface` | Register client tool ID and handler index; return handler index | Projection-settings changes |
|
| 40 |
+
| `log.!interface` | Register a log handle and post messages through task buffers | String/integer-buffer conversion and message ownership need runtime tests |
|
| 41 |
+
| `pluginsMenu.!interface` | Register caption plus callback target/index; toggle/toggle-at; click response | Registration collection is scheduled through task priorities |
|
| 42 |
+
| `raycast.!interface` | Request `[0, replyTool, pastNearClip]` + two vec3s; response `[0, hit]` + hit point/normal if hit | One client callback slot; host path can temporarily alter selection |
|
| 43 |
+
| `taskPriorities.!interface` | Request `[0, replyTool] + name`; response `[0, priority]` | Missing service replies synchronously with 0; configured names use first-match lookup |
|
| 44 |
+
| `viewEvents.!interface` | Register listener, notify created/cloned/closing/closed; fan out IDs | Closing and closed are separate phases |
|
| 45 |
+
| `worldController.!interface` | Register first view of a new world | Applies background color and publishes a created event |
|
| 46 |
+
|
| 47 |
+
For camera/grid/projections, source helpers store callback plus a tag and send a zero-based handler index to the provider. Negative/invalid indices, malformed payload buffers, lifetime and concurrency rules remain unspecified. In particular, do not assume these helpers validate every incoming buffer.
|
| 48 |
+
|
| 49 |
+
## Registration and lifecycle
|
| 50 |
+
|
| 51 |
+
`Akula.ixpl:988–1034` shows that `initTool` fills press/release/abort/task callbacks and integer tags; `initPackage` stores a tool list; `registerPackage` iterates it and calls `registerTool`. Static blocks register packages and runtime callbacks. Core version validation is also in a static block.
|
| 52 |
+
|
| 53 |
+
Most UI plugins register all-loaded initialization and finalization saves. Grid/projections/render modes also register view-selected handlers; editing tools register view-mouse-move and camera-tick handlers. Core comments say `selectView` itself does not trigger view-selected notification and tasks cannot be queued from static blocks. A Rust event model must represent these distinctions explicitly.
|
| 54 |
+
|
| 55 |
+
`world controller.ixpl:96–100,137–150` publishes “closing”, queues a task with the configured priority, then closes the view and publishes “closed” when that task is handled. Resource cleanup cannot assume the initial close request is the actual destruction point.
|
| 56 |
+
|
| 57 |
+
`raycast.ixpl:40–61` temporarily selects an unselected hit into the main set to read its plane, then deselects via another ray call. This is an observed source sequence, not a reproduced visible selection bug. It is a focused equivalence test for a future side-effect-free Rust picking implementation.
|
| 58 |
+
|
| 59 |
+
## Experimental modules
|
| 60 |
+
|
| 61 |
+
`extra stuff/readme.txt` labels these unfinished/experimental and describes manually copying source into the top-level plugin directory before compilation and adding a binding.
|
| 62 |
+
|
| 63 |
+
- `AAA_bevel`: ray-targeted bevel helper; geometry behavior and numerical limits remain open.
|
| 64 |
+
- `AAA_lego`: procedural brush construction example, registering `Lego.!interface`.
|
| 65 |
+
- `AAA_patchtest`: curved-patch construction experiment, registering `Patchtest.!interface`.
|
| 66 |
+
- `AAA_blank` and `AAA_blank (2)`: extension templates. Both declare the same `Blank.!interface` name; do not assume they can be enabled together without a name collision.
|
| 67 |
+
|
| 68 |
+
Native functionality and third-party compiled-plugin compatibility remain separate product decisions. No IXPL VM/compiler or Rust plugin system is selected by this mapping pass.
|
| 69 |
+
|
| 70 |
+
Next: P4.04/P4.05 lifecycle and protocol experiments, P4.08 module behavior specifications, and P7 complete tool state machines. The index maps registration/call dependencies without closing those parity tasks.
|
docs/PLUGIN_INDEX.md
ADDED
|
@@ -0,0 +1,358 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Plugin tool registration index
|
| 2 |
+
|
| 3 |
+
Baseline `2016-03-10-c`. These are lexical `initTool` call sites, including internal/service tools and experiments. Conservative name resolution does not prove runtime reachability, load order or simultaneous registration. See [PLUGINS.md](PLUGINS.md).
|
| 4 |
+
|
| 5 |
+
## GUI layout designer
|
| 6 |
+
|
| 7 |
+
Source: `data/sources/plugins/GUI layout designer.ixpl`; SHA-256 `6f18662ac0359973a551a23b00a36e566bf6ff31e4f9b46bd8e19cd0d6ae0427`.
|
| 8 |
+
|
| 9 |
+
| Tool name expression resolved to | Line | Press callback expression |
|
| 10 |
+
| --- | ---: | --- |
|
| 11 |
+
| `GUILayoutDesigner.toggleMain` | 146 | `H::onToggleMain<int>` |
|
| 12 |
+
|
| 13 |
+
## Mb3 main editing tools
|
| 14 |
+
|
| 15 |
+
Source: `data/sources/plugins/Mb3 main editing tools.ixpl`; SHA-256 `4c01de0d5ec43334ecb9b27f1c1c3e269636a9d40f3c50a0f986a1e541cd90c4`.
|
| 16 |
+
|
| 17 |
+
| Tool name expression resolved to | Line | Press callback expression |
|
| 18 |
+
| --- | ---: | --- |
|
| 19 |
+
| `Mb3MainEditingTools.!interface` | 352 | `f` |
|
| 20 |
+
| `Mb3MainEditingTools.toggleMain` | 354 | `H::onToggleMain <int>` |
|
| 21 |
+
| `Mb3MainEditingTools.toggleMainH` | 355 | `H::onToggleMainH <int>` |
|
| 22 |
+
| `Mb3MainEditingTools.toggleMainV` | 356 | `H::onToggleMainV <int>` |
|
| 23 |
+
| `Mb3MainEditingTools.toolMain` | 357 | `onToolMainDown <int>` |
|
| 24 |
+
| `Mb3MainEditingTools.toolAlt` | 358 | `onToolAlt <int>` |
|
| 25 |
+
| `Mb3MainEditingTools.makeBox` | 359 | `liveToolStart <int>` |
|
| 26 |
+
| `Mb3MainEditingTools.move` | 360 | `liveToolStart <int>` |
|
| 27 |
+
| `Mb3MainEditingTools.copyMove` | 361 | `liveToolStart <int>` |
|
| 28 |
+
| `Mb3MainEditingTools.mirror` | 362 | `liveToolStart <int>` |
|
| 29 |
+
| `Mb3MainEditingTools.mirrorAlt` | 363 | `liveToolStart <int>` |
|
| 30 |
+
| `Mb3MainEditingTools.rotateLeft90` | 364 | `liveToolStart <int>` |
|
| 31 |
+
| `Mb3MainEditingTools.rotateLeft90Alt` | 365 | `liveToolStart <int>` |
|
| 32 |
+
| `Mb3MainEditingTools.rotateRight90` | 366 | `liveToolStart <int>` |
|
| 33 |
+
| `Mb3MainEditingTools.rotateRight90Alt` | 367 | `liveToolStart <int>` |
|
| 34 |
+
| `Mb3MainEditingTools.dragFacing` | 368 | `liveToolStart <int>` |
|
| 35 |
+
| `Mb3MainEditingTools.deleteSelected` | 369 | `H::onTDeleteSelected <int>` |
|
| 36 |
+
| `Mb3MainEditingTools.clip2` | 370 | `liveToolStart <int>` |
|
| 37 |
+
| `Mb3MainEditingTools.clip3` | 371 | `liveToolStart <int>` |
|
| 38 |
+
| `Mb3MainEditingTools.merge` | 372 | `H::onTMerge <int>` |
|
| 39 |
+
| `Mb3MainEditingTools.intersect` | 373 | `H::onTIntersect <int>` |
|
| 40 |
+
| `Mb3MainEditingTools.doubleSize` | 374 | `liveToolStart <int>` |
|
| 41 |
+
| `Mb3MainEditingTools.doubleSizeAlt` | 375 | `liveToolStart <int>` |
|
| 42 |
+
| `Mb3MainEditingTools.halveSize` | 376 | `liveToolStart <int>` |
|
| 43 |
+
| `Mb3MainEditingTools.halveSizeAlt` | 377 | `liveToolStart <int>` |
|
| 44 |
+
| `Mb3MainEditingTools.hideSelected` | 378 | `H::onTHideSelected <int>` |
|
| 45 |
+
| `Mb3MainEditingTools.showHidden` | 379 | `H::onTShowHidden <int>` |
|
| 46 |
+
| `Mb3MainEditingTools.paintSelect` | 380 | `liveToolStart <int>` |
|
| 47 |
+
| `Mb3MainEditingTools.selectAll` | 381 | `H::onTSelectAll <int>` |
|
| 48 |
+
| `Mb3MainEditingTools.deselectAll` | 382 | `H::onTDeselectAll <int>` |
|
| 49 |
+
| `Mb3MainEditingTools.invertSelection` | 383 | `H::onTInvertSelection <int>` |
|
| 50 |
+
| `Mb3MainEditingTools.deselectSelSet1` | 384 | `H::onTDeselectSelSet1 <int>` |
|
| 51 |
+
| `Mb3MainEditingTools.deselectSelSet2` | 385 | `H::onTDeselectSelSet2 <int>` |
|
| 52 |
+
| `Mb3MainEditingTools.deleteSelSet1` | 386 | `H::onTDeleteSelSet1 <int>` |
|
| 53 |
+
| `Mb3MainEditingTools.deleteSelSet2` | 387 | `H::onTDeleteSelSet2 <int>` |
|
| 54 |
+
| `Mb3MainEditingTools.selectInAABB` | 388 | `H::onTSelectInAABB <int>` |
|
| 55 |
+
| `Mb3MainEditingTools.selectTouchingAABB` | 389 | `H::onTSelectTouchingAABB <int>` |
|
| 56 |
+
| `Mb3MainEditingTools.selectInBrush` | 390 | `H::onTSelectInBrush <int>` |
|
| 57 |
+
| `Mb3MainEditingTools.selectTouchingBrush` | 391 | `H::onTSelectTouchingBrush<int>` |
|
| 58 |
+
| `Mb3MainEditingTools.undo` | 392 | `H::onTUndo <int>` |
|
| 59 |
+
| `Mb3MainEditingTools.redo` | 393 | `H::onTRedo <int>` |
|
| 60 |
+
|
| 61 |
+
## Mb3 plugins
|
| 62 |
+
|
| 63 |
+
Source: `data/sources/plugins/Mb3 plugins.ixpl`; SHA-256 `fa1efa33e0bbdef7d6e6d80fc8739fc2c20970a209bcae812004e51102a8a890`.
|
| 64 |
+
|
| 65 |
+
| Tool name expression resolved to | Line | Press callback expression |
|
| 66 |
+
| --- | ---: | --- |
|
| 67 |
+
| `Mb3Plugins.toggleMain` | 87 | `H::onToggleMain<int>` |
|
| 68 |
+
|
| 69 |
+
## Mb3 render modes
|
| 70 |
+
|
| 71 |
+
Source: `data/sources/plugins/Mb3 render modes.ixpl`; SHA-256 `1e6c1a8c10cfe311b6ea24f632be084c2a26f4d96294a44dedaef6aae0b90ae2`.
|
| 72 |
+
|
| 73 |
+
| Tool name expression resolved to | Line | Press callback expression |
|
| 74 |
+
| --- | ---: | --- |
|
| 75 |
+
| `Mb3RenderModes.!interface` | 136 | `f` |
|
| 76 |
+
| `Mb3RenderModes.toggleMain` | 138 | `H::onToggleMain <int>` |
|
| 77 |
+
| `Mb3RenderModes.toggleMainH` | 139 | `H::onToggleMainH<int>` |
|
| 78 |
+
| `Mb3RenderModes.toggleMainV` | 140 | `H::onToggleMainV<int>` |
|
| 79 |
+
| `Mb3RenderModes.mode0` | 141 | `H::onMode0 <int>` |
|
| 80 |
+
| `Mb3RenderModes.mode1` | 142 | `H::onMode1 <int>` |
|
| 81 |
+
| `Mb3RenderModes.mode2` | 143 | `H::onMode2 <int>` |
|
| 82 |
+
| `Mb3RenderModes.mode3` | 144 | `H::onMode3 <int>` |
|
| 83 |
+
| `Mb3RenderModes.mode4` | 145 | `H::onMode4 <int>` |
|
| 84 |
+
| `Mb3RenderModes.mode5` | 146 | `H::onMode5 <int>` |
|
| 85 |
+
|
| 86 |
+
## camera
|
| 87 |
+
|
| 88 |
+
Source: `data/sources/plugins/camera.ixpl`; SHA-256 `6702568d832d8b5bff7abd31e2a5a0a6dc70d8a4e118b2028312dbb44669a066`.
|
| 89 |
+
|
| 90 |
+
| Tool name expression resolved to | Line | Press callback expression |
|
| 91 |
+
| --- | ---: | --- |
|
| 92 |
+
| `camera.toggleMenu` | 283 | `CH::onToggleMenu <int>` |
|
| 93 |
+
| `camera.editCurrentAsText` | 284 | `f` |
|
| 94 |
+
| `camera.useMemory1` | 285 | `CH::onUseMemory1 <int>` |
|
| 95 |
+
| `camera.useMemory2` | 286 | `CH::onUseMemory2 <int>` |
|
| 96 |
+
| `camera.useMemory3` | 287 | `CH::onUseMemory3 <int>` |
|
| 97 |
+
| `camera.useMemory4` | 288 | `CH::onUseMemory4 <int>` |
|
| 98 |
+
| `camera.useMemory5` | 289 | `CH::onUseMemory5 <int>` |
|
| 99 |
+
| `camera.useMemory6` | 290 | `CH::onUseMemory6 <int>` |
|
| 100 |
+
| `camera.useMemory7` | 291 | `CH::onUseMemory7 <int>` |
|
| 101 |
+
| `camera.useMemory8` | 292 | `CH::onUseMemory8 <int>` |
|
| 102 |
+
| `camera.useMemory9` | 293 | `CH::onUseMemory9 <int>` |
|
| 103 |
+
| `camera.useMemory0` | 294 | `CH::onUseMemory0 <int>` |
|
| 104 |
+
| `camera.save` | 295 | `CH::onSave <int>` |
|
| 105 |
+
| `camera.toggleFlyMode` | 296 | `CH::onToggleFlyMode <int>` |
|
| 106 |
+
| `camera.flyForward` | 297 | `CH::onFlyForwardDown <int>` |
|
| 107 |
+
| `camera.flyBackward` | 298 | `CH::onFlyBackwardDown <int>` |
|
| 108 |
+
| `camera.flyLeft` | 299 | `CH::onFlyLeftDown <int>` |
|
| 109 |
+
| `camera.flyRight` | 300 | `CH::onFlyRightDown <int>` |
|
| 110 |
+
| `camera.flyUp` | 301 | `CH::onFlyUpDown <int>` |
|
| 111 |
+
| `camera.flyDown` | 302 | `CH::onFlyDownDown <int>` |
|
| 112 |
+
| `camera.turnLeft` | 303 | `CH::onTurnLeftDown <int>` |
|
| 113 |
+
| `camera.turnRight` | 304 | `CH::onTurnRightDown <int>` |
|
| 114 |
+
| `camera.lookUp` | 305 | `CH::onLookUpDown <int>` |
|
| 115 |
+
| `camera.lookDown` | 306 | `CH::onLookDownDown <int>` |
|
| 116 |
+
| `camera.leanLeft` | 307 | `CH::onLeanLeftDown <int>` |
|
| 117 |
+
| `camera.leanRight` | 308 | `CH::onLeanRightDown <int>` |
|
| 118 |
+
| `camera.turnModifier` | 309 | `CH::onTurnModifierDown<int>` |
|
| 119 |
+
| `camera.doubleSpeed` | 310 | `CH::onDoubleSpeed <int>` |
|
| 120 |
+
| `camera.halveSpeed` | 311 | `CH::onHalveSpeed <int>` |
|
| 121 |
+
| `camera.reset` | 312 | `CH::onReset <int>` |
|
| 122 |
+
| `camera.resetLeaning` | 313 | `CH::onResetLeaning <int>` |
|
| 123 |
+
| `camera.!interface` | 314 | `f` |
|
| 124 |
+
|
| 125 |
+
## AAA_bevel
|
| 126 |
+
|
| 127 |
+
Source: `data/sources/plugins/extra stuff/AAA_bevel.ixpl`; SHA-256 `0f35085290d387eaeef817a46b25d8aadce7caf71de54b1b44807d444dca9432`.
|
| 128 |
+
|
| 129 |
+
| Tool name expression resolved to | Line | Press callback expression |
|
| 130 |
+
| --- | ---: | --- |
|
| 131 |
+
| `AAA_bevel.T1` | 17 | `onT1<int>` |
|
| 132 |
+
|
| 133 |
+
## AAA_blank (2)
|
| 134 |
+
|
| 135 |
+
Source: `data/sources/plugins/extra stuff/AAA_blank (2).ixpl`; SHA-256 `3e1a5ed02e92eca4b65714899565ac49daee6bc27d304cb43c0e836190cb115e`.
|
| 136 |
+
|
| 137 |
+
| Tool name expression resolved to | Line | Press callback expression |
|
| 138 |
+
| --- | ---: | --- |
|
| 139 |
+
| `Blank.!interface` | 23 | `f` |
|
| 140 |
+
| `Blank.T1` | 25 | `onT1<int>` |
|
| 141 |
+
|
| 142 |
+
## AAA_blank
|
| 143 |
+
|
| 144 |
+
Source: `data/sources/plugins/extra stuff/AAA_blank.ixpl`; SHA-256 `ff7c785412fb233d339a0b475030824c1c067c3fb7c6e52fb0c92a0a4c98dd3e`.
|
| 145 |
+
|
| 146 |
+
| Tool name expression resolved to | Line | Press callback expression |
|
| 147 |
+
| --- | ---: | --- |
|
| 148 |
+
| `Blank.!interface` | 23 | `f` |
|
| 149 |
+
| `Blank.T1` | 25 | `onT1<int>` |
|
| 150 |
+
|
| 151 |
+
## AAA_lego
|
| 152 |
+
|
| 153 |
+
Source: `data/sources/plugins/extra stuff/AAA_lego.ixpl`; SHA-256 `d04927276628cc42026de067a1503ade32a48543100957dbbf8cf23dd967affd`.
|
| 154 |
+
|
| 155 |
+
| Tool name expression resolved to | Line | Press callback expression |
|
| 156 |
+
| --- | ---: | --- |
|
| 157 |
+
| `Lego.!interface` | 27 | `f` |
|
| 158 |
+
|
| 159 |
+
## AAA_patchtest
|
| 160 |
+
|
| 161 |
+
Source: `data/sources/plugins/extra stuff/AAA_patchtest.ixpl`; SHA-256 `5c5b3be7d4dbe10337526d655ed930ae4a844b992000a09c6eed70283d7ba875`.
|
| 162 |
+
|
| 163 |
+
| Tool name expression resolved to | Line | Press callback expression |
|
| 164 |
+
| --- | ---: | --- |
|
| 165 |
+
| `Patchtest.!interface` | 22 | `f` |
|
| 166 |
+
|
| 167 |
+
## grid
|
| 168 |
+
|
| 169 |
+
Source: `data/sources/plugins/grid.ixpl`; SHA-256 `14d3fe20e969d13ade976d2481a1a34ce459a3cb8ab3d99d6905866aef0f3220`.
|
| 170 |
+
|
| 171 |
+
| Tool name expression resolved to | Line | Press callback expression |
|
| 172 |
+
| --- | ---: | --- |
|
| 173 |
+
| `grid.toggleMenu` | 556 | `CH::onToggleMenu <int>` |
|
| 174 |
+
| `grid.toggleCircular` | 557 | `CH::onToggleCircular <int>` |
|
| 175 |
+
| `grid.toggleFlat` | 558 | `CH::onToggleFlat <int>` |
|
| 176 |
+
| `grid.toggleSnapToX` | 559 | `CH::onToggleSnapX <int>` |
|
| 177 |
+
| `grid.toggleSnapToY` | 560 | `CH::onToggleSnapY <int>` |
|
| 178 |
+
| `grid.toggleSnapToZ` | 561 | `CH::onToggleSnapZ <int>` |
|
| 179 |
+
| `grid.toggleSnapToCircles` | 562 | `CH::onToggleCircles <int>` |
|
| 180 |
+
| `grid.toggleSnapToCenterLines` | 563 | `CH::onToggleCenterLines <int>` |
|
| 181 |
+
| `grid.toggleSecondarySnapping` | 564 | `CH::onToggleSecondarySnap <int>` |
|
| 182 |
+
| `grid.toggleActive` | 565 | `CH::onToggleActive <int>` |
|
| 183 |
+
| `grid.resolutionInc` | 566 | `CH::onResolutionInc <int>` |
|
| 184 |
+
| `grid.resolutionDec` | 567 | `CH::onResolutionDec <int>` |
|
| 185 |
+
| `grid.resolutionAroundInc` | 568 | `CH::onOResolutionInc <int>` |
|
| 186 |
+
| `grid.resolutionAroundDec` | 569 | `CH::onOResolutionDec <int>` |
|
| 187 |
+
| `grid.secondaryResolutionInc` | 570 | `CH::onSecResolutionInc <int>` |
|
| 188 |
+
| `grid.secondaryResolutionDec` | 571 | `CH::onSecResolutionDec <int>` |
|
| 189 |
+
| `grid.originOnGrid` | 572 | `CH::onOriginOnGrid <int>` |
|
| 190 |
+
| `grid.originOnObjectOrGrid` | 573 | `CH::onOriginOnObjectOrGrid<int>` |
|
| 191 |
+
| `grid.facePlaneOnObject` | 574 | `CH::onFacePlaneOnObject <int>` |
|
| 192 |
+
| `grid.reset` | 575 | `CH::onReset <int>` |
|
| 193 |
+
| `grid.resolution` | 576 | `f` |
|
| 194 |
+
| `grid.resolutionBase` | 577 | `f` |
|
| 195 |
+
| `grid.resolutionAround` | 578 | `f` |
|
| 196 |
+
| `grid.resolutionBaseAround` | 579 | `f` |
|
| 197 |
+
| `grid.secondaryResolution` | 580 | `f` |
|
| 198 |
+
| `grid.secondaryResolutionBase` | 581 | `f` |
|
| 199 |
+
| `grid.cellsPerMajor` | 582 | `f` |
|
| 200 |
+
| `grid.majorsAtResolution0` | 583 | `f` |
|
| 201 |
+
| `grid.cellsPerMajorAround` | 584 | `f` |
|
| 202 |
+
| `grid.majorsAtResolution0Around` | 585 | `f` |
|
| 203 |
+
| `grid.axisAlignmentBias` | 586 | `f` |
|
| 204 |
+
| `grid.origin` | 587 | `f` |
|
| 205 |
+
| `grid.axisX` | 588 | `f` |
|
| 206 |
+
| `grid.axisY` | 589 | `f` |
|
| 207 |
+
| `grid.axisZ` | 590 | `f` |
|
| 208 |
+
| `grid.useMemory1` | 591 | `CH::onUseMemory1 <int>` |
|
| 209 |
+
| `grid.useMemory2` | 592 | `CH::onUseMemory2 <int>` |
|
| 210 |
+
| `grid.useMemory3` | 593 | `CH::onUseMemory3 <int>` |
|
| 211 |
+
| `grid.useMemory4` | 594 | `CH::onUseMemory4 <int>` |
|
| 212 |
+
| `grid.useMemory5` | 595 | `CH::onUseMemory5 <int>` |
|
| 213 |
+
| `grid.useMemory6` | 596 | `CH::onUseMemory6 <int>` |
|
| 214 |
+
| `grid.useMemory7` | 597 | `CH::onUseMemory7 <int>` |
|
| 215 |
+
| `grid.useMemory8` | 598 | `CH::onUseMemory8 <int>` |
|
| 216 |
+
| `grid.useMemory9` | 599 | `CH::onUseMemory9 <int>` |
|
| 217 |
+
| `grid.useMemory0` | 600 | `CH::onUseMemory0 <int>` |
|
| 218 |
+
| `grid.save` | 601 | `CH::onSave <int>` |
|
| 219 |
+
| `grid.!interface` | 602 | `f` |
|
| 220 |
+
|
| 221 |
+
## log
|
| 222 |
+
|
| 223 |
+
Source: `data/sources/plugins/log.ixpl`; SHA-256 `9131b4ec7b099721819b8280d0874c41805077863afeee1428507a43beb2477f`.
|
| 224 |
+
|
| 225 |
+
| Tool name expression resolved to | Line | Press callback expression |
|
| 226 |
+
| --- | ---: | --- |
|
| 227 |
+
| `log.!interface` | 171 | `f` |
|
| 228 |
+
| `log.toggleMain` | 173 | `CH::onToggleMain <int>` |
|
| 229 |
+
| `log.showAll` | 174 | `f` |
|
| 230 |
+
| `log.toggleConfig` | 175 | `CH::onToggleConfig<int>` |
|
| 231 |
+
|
| 232 |
+
## main menu
|
| 233 |
+
|
| 234 |
+
Source: `data/sources/plugins/main menu.ixpl`; SHA-256 `bd67c9c15b0fd2d03c3af86b90a3992df6f64cb6aa9c1a2561f95d56457835ed`.
|
| 235 |
+
|
| 236 |
+
| Tool name expression resolved to | Line | Press callback expression |
|
| 237 |
+
| --- | ---: | --- |
|
| 238 |
+
| `mainMenu.toggleMain` | 225 | `H::onToggleMain<int>` |
|
| 239 |
+
| `mainMenu.newWorld` | 226 | `H::onNewWorld <int>` |
|
| 240 |
+
| `mainMenu.save` | 227 | `f` |
|
| 241 |
+
| `mainMenu.loadMb3TXTDAT` | 228 | `f` |
|
| 242 |
+
| `mainMenu.loadHL1MAP` | 229 | `f` |
|
| 243 |
+
| `mainMenu.loadHL2VMF` | 230 | `f` |
|
| 244 |
+
| `mainMenu.loadQ3MAP` | 231 | `f` |
|
| 245 |
+
| `mainMenu.saveAsMb3TXT` | 232 | `f` |
|
| 246 |
+
| `mainMenu.saveAsMb3DAT` | 233 | `f` |
|
| 247 |
+
| `mainMenu.saveAsHL1MAP` | 234 | `f` |
|
| 248 |
+
| `mainMenu.saveAsHL2VMF` | 235 | `f` |
|
| 249 |
+
| `mainMenu.saveAsQ3MAP` | 236 | `f` |
|
| 250 |
+
| `mainMenu.exportMb3TXTComp` | 237 | `f` |
|
| 251 |
+
| `mainMenu.exportWfOBJ` | 238 | `f` |
|
| 252 |
+
|
| 253 |
+
## notes
|
| 254 |
+
|
| 255 |
+
Source: `data/sources/plugins/notes.ixpl`; SHA-256 `814dc52146c82b70f8548ba3989ae0b99a29e52ad0dfba5fb27d093537297d25`.
|
| 256 |
+
|
| 257 |
+
| Tool name expression resolved to | Line | Press callback expression |
|
| 258 |
+
| --- | ---: | --- |
|
| 259 |
+
| `notes.toggleMain` | 112 | `H::onToggleMain <int>` |
|
| 260 |
+
| `notes.notesNew` | 113 | `f` |
|
| 261 |
+
| `notes.notesSave` | 114 | `H::onMainNotesSave <int>` |
|
| 262 |
+
| `notes.archiveRestore` | 115 | `f` |
|
| 263 |
+
| `notes.archiveClear` | 116 | `H::onMainArchiveClear<int>` |
|
| 264 |
+
|
| 265 |
+
## plugins menu
|
| 266 |
+
|
| 267 |
+
Source: `data/sources/plugins/plugins menu.ixpl`; SHA-256 `fcabcb9016591763fa487ecde922359f41ea48e8253f417f22a72c41da7051e1`.
|
| 268 |
+
|
| 269 |
+
| Tool name expression resolved to | Line | Press callback expression |
|
| 270 |
+
| --- | ---: | --- |
|
| 271 |
+
| `pluginsMenu.!interface` | 66 | `f` |
|
| 272 |
+
| `pluginsMenu.toggle` | 68 | `CH::onToggle<int>` |
|
| 273 |
+
|
| 274 |
+
## projections
|
| 275 |
+
|
| 276 |
+
Source: `data/sources/plugins/projections.ixpl`; SHA-256 `3d2518597a254cda21e22e9e5fe85c9a3369c7533064178a23c51ae50d5beae7`.
|
| 277 |
+
|
| 278 |
+
| Tool name expression resolved to | Line | Press callback expression |
|
| 279 |
+
| --- | ---: | --- |
|
| 280 |
+
| `projections.toggleMenu` | 209 | `CH::onToggleMenu<int>` |
|
| 281 |
+
| `projections.editCurrentAsText` | 210 | `f` |
|
| 282 |
+
| `projections.useMemory1` | 211 | `CH::onUseMemory1<int>` |
|
| 283 |
+
| `projections.useMemory2` | 212 | `CH::onUseMemory2<int>` |
|
| 284 |
+
| `projections.useMemory3` | 213 | `CH::onUseMemory3<int>` |
|
| 285 |
+
| `projections.useMemory4` | 214 | `CH::onUseMemory4<int>` |
|
| 286 |
+
| `projections.useMemory5` | 215 | `CH::onUseMemory5<int>` |
|
| 287 |
+
| `projections.useMemory6` | 216 | `CH::onUseMemory6<int>` |
|
| 288 |
+
| `projections.useMemory7` | 217 | `CH::onUseMemory7<int>` |
|
| 289 |
+
| `projections.useMemory8` | 218 | `CH::onUseMemory8<int>` |
|
| 290 |
+
| `projections.useMemory9` | 219 | `CH::onUseMemory9<int>` |
|
| 291 |
+
| `projections.useMemory0` | 220 | `CH::onUseMemory0<int>` |
|
| 292 |
+
| `projections.save` | 221 | `CH::onSave <int>` |
|
| 293 |
+
| `projections.!interface` | 222 | `f` |
|
| 294 |
+
|
| 295 |
+
## raycast
|
| 296 |
+
|
| 297 |
+
Source: `data/sources/plugins/raycast.ixpl`; SHA-256 `a924e585e2c303e76a174383662317c9c34e5a8e45a1dd5f129852ffa33d42cb`.
|
| 298 |
+
|
| 299 |
+
| Tool name expression resolved to | Line | Press callback expression |
|
| 300 |
+
| --- | ---: | --- |
|
| 301 |
+
| `raycast.!interface` | 22 | `f` |
|
| 302 |
+
|
| 303 |
+
## task priorities
|
| 304 |
+
|
| 305 |
+
Source: `data/sources/plugins/task priorities.ixpl`; SHA-256 `f2fc980be71cdbf9cec56cb15b6515b3a0e5e5ea4821444e5ce934f5b200af5b`.
|
| 306 |
+
|
| 307 |
+
| Tool name expression resolved to | Line | Press callback expression |
|
| 308 |
+
| --- | ---: | --- |
|
| 309 |
+
| `taskPriorities.!interface` | 28 | `f` |
|
| 310 |
+
|
| 311 |
+
## view events
|
| 312 |
+
|
| 313 |
+
Source: `data/sources/plugins/view events.ixpl`; SHA-256 `7176e5b93499e92966af0f2c72a767e738ac0c8779f677fbd200739e1451cc02`.
|
| 314 |
+
|
| 315 |
+
| Tool name expression resolved to | Line | Press callback expression |
|
| 316 |
+
| --- | ---: | --- |
|
| 317 |
+
| `viewEvents.!interface` | 25 | `f` |
|
| 318 |
+
|
| 319 |
+
## view layouts
|
| 320 |
+
|
| 321 |
+
Source: `data/sources/plugins/view layouts.ixpl`; SHA-256 `de03e1ce505ea9f220ede29c654061865f8c578514d05b3b7a912da0e08fd1eb`.
|
| 322 |
+
|
| 323 |
+
| Tool name expression resolved to | Line | Press callback expression |
|
| 324 |
+
| --- | ---: | --- |
|
| 325 |
+
| `viewLayouts.!interface` | 133 | `f` |
|
| 326 |
+
| `viewLayouts.toggleMain` | 135 | `H::onToggleMain <int>` |
|
| 327 |
+
| `viewLayouts.toggleMainH` | 136 | `H::onToggleMainH<int>` |
|
| 328 |
+
| `viewLayouts.toggleMainV` | 137 | `H::onToggleMainV<int>` |
|
| 329 |
+
| `viewLayouts.layout0` | 138 | `H::onLayout0 <int>` |
|
| 330 |
+
| `viewLayouts.layout1` | 139 | `H::onLayout1 <int>` |
|
| 331 |
+
| `viewLayouts.layout2` | 140 | `H::onLayout2 <int>` |
|
| 332 |
+
| `viewLayouts.layout3` | 141 | `H::onLayout3 <int>` |
|
| 333 |
+
| `viewLayouts.layout4` | 142 | `H::onLayout4 <int>` |
|
| 334 |
+
| `viewLayouts.layout5` | 143 | `H::onLayout5 <int>` |
|
| 335 |
+
|
| 336 |
+
## window controls
|
| 337 |
+
|
| 338 |
+
Source: `data/sources/plugins/window controls.ixpl`; SHA-256 `8f38720c74dafc694a2b1a66c3b46c55f39b7f5f1ccfeb741545a3ba585caa1f`.
|
| 339 |
+
|
| 340 |
+
| Tool name expression resolved to | Line | Press callback expression |
|
| 341 |
+
| --- | ---: | --- |
|
| 342 |
+
| `main.fullscreen` | 25 | `toggleFullscreen <int>` |
|
| 343 |
+
| `main.fakeFullscreen` | 26 | `toggleFakeFullscreen<int>` |
|
| 344 |
+
| `main.setFPS` | 27 | `f` |
|
| 345 |
+
|
| 346 |
+
## world controller
|
| 347 |
+
|
| 348 |
+
Source: `data/sources/plugins/world controller.ixpl`; SHA-256 `93e1e21e46e4292be1c0c2fc5a084e238a3ccd2317ca44d83fc12f6c6b7e1280`.
|
| 349 |
+
|
| 350 |
+
| Tool name expression resolved to | Line | Press callback expression |
|
| 351 |
+
| --- | ---: | --- |
|
| 352 |
+
| `worldController.!interface` | 50 | `f` |
|
| 353 |
+
| `worldController.cloneView` | 52 | `onCloneView <int>` |
|
| 354 |
+
| `worldController.maximizeView` | 53 | `onMaximizeView <int>` |
|
| 355 |
+
| `worldController.minimizeView` | 54 | `onMinimizeView <int>` |
|
| 356 |
+
| `worldController.restoreView` | 55 | `onRestoreView <int>` |
|
| 357 |
+
| `worldController.toggleViewFocusLock` | 56 | `onToggleViewFocusLock<int>` |
|
| 358 |
+
| `worldController.closeView` | 57 | `onCloseView <int>` |
|
docs/README.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
| 2 |
|
| 3 |
Planning baseline: 2026-10-21. Project name: **Nanobrush**; reference software: **Microbrush 3 / Iteration X / Akula**.
|
| 4 |
|
| 5 |
-
The intended result is a complete native Rust and Bevy reconstruction for macOS and Linux, with Solari lighting on supported hardware.
|
| 6 |
|
| 7 |
| Document | Purpose |
|
| 8 |
| --- | --- |
|
|
@@ -14,7 +14,9 @@ The intended result is a complete native Rust and Bevy reconstruction for macOS
|
|
| 14 |
| [Investigation method](REVERSE_ENGINEERING.md) | How to investigate, record evidence, and prove behavioral equivalence |
|
| 15 |
| [Technical direction](TECHNICAL_DIRECTION.md) | Proposed repository boundaries, asset pipeline, Rust modules, and rendering strategy |
|
| 16 |
|
| 17 |
-
|
|
|
|
|
|
|
| 18 |
|
| 19 |
## Status vocabulary
|
| 20 |
|
|
@@ -27,7 +29,7 @@ Repository storage/environment and reference extraction are implemented; consult
|
|
| 27 |
|
| 28 |
## Planning validation
|
| 29 |
|
| 30 |
-
The backlog
|
| 31 |
|
| 32 |
## Maintaining this plan
|
| 33 |
|
|
|
|
| 2 |
|
| 3 |
Planning baseline: 2026-10-21. Project name: **Nanobrush**; reference software: **Microbrush 3 / Iteration X / Akula**.
|
| 4 |
|
| 5 |
+
The intended result is a complete native Rust and Bevy reconstruction for macOS and Linux, with Solari lighting on supported hardware. The initial plan is complete, and source-level reverse engineering is now underway. Repository setup and permanent extraction are now implemented; see [setup validation](SETUP.md). Conversion and application implementation remain future work.
|
| 6 |
|
| 7 |
| Document | Purpose |
|
| 8 |
| --- | --- |
|
|
|
|
| 14 |
| [Investigation method](REVERSE_ENGINEERING.md) | How to investigate, record evidence, and prove behavioral equivalence |
|
| 15 |
| [Technical direction](TECHNICAL_DIRECTION.md) | Proposed repository boundaries, asset pipeline, Rust modules, and rendering strategy |
|
| 16 |
|
| 17 |
+
The first source investigation is documented in [formats](FORMATS.md), [host APIs](HOST_APIS.md), [plugins](PLUGINS.md), and [dependencies](DEPENDENCIES.md). Complete latest-source endpoint/tool lists are in [API_INDEX.md](API_INDEX.md) and [PLUGIN_INDEX.md](PLUGIN_INDEX.md). See the [coverage ledger](parity.md), [risks](risks.md), [validation](validation.md), and [E01 experiment](experiments/static-map-2026-10-21.md) for evidence and limits.
|
| 18 |
+
|
| 19 |
+
The asset boundary and extraction pipeline are established. Continue with the open P0 decisions and P3–P9 investigation tasks in `TODO.md`, using the source maps to design focused runtime experiments. Run the rendering capability spike early, independently of most editor research. Implement the rewrite in small end-to-end slices after the corresponding behavior is specified.
|
| 20 |
|
| 21 |
## Status vocabulary
|
| 22 |
|
|
|
|
| 29 |
|
| 30 |
## Planning validation
|
| 31 |
|
| 32 |
+
The original planning backlog contained 197 tasks across 17 phases; source-research subtasks have since been added in TODO.md. The inventory covers all 560 regular-member occurrences (132 distinct paths) and every explicit directory entry across the five ZIPs. Original archive SHA-256 values and CRCs passed; document links, code fences, task IDs, and inventory coverage were checked. Application behavior and GPU support remain untested; repository setup validation is recorded in SETUP.md.
|
| 33 |
|
| 34 |
## Maintaining this plan
|
| 35 |
|
docs/REVERSE_ENGINEERING.md
CHANGED
|
@@ -50,7 +50,7 @@ docs/
|
|
| 50 |
validation.md # platform, corpus, hardware and release results
|
| 51 |
```
|
| 52 |
|
| 53 |
-
|
| 54 |
|
| 55 |
## Investigation sequence
|
| 56 |
|
|
|
|
| 50 |
validation.md # platform, corpus, hardware and release results
|
| 51 |
```
|
| 52 |
|
| 53 |
+
The initial maps currently live at docs/FORMATS.md, HOST_APIS.md, PLUGINS.md and DEPENDENCIES.md, with E01, D01, parity and validation records. Split them into the proposed specifications structure as behavioral contracts mature. Raw binaries, extracted third-party source, fixture documents, PNGs/video, and generated analysis dumps stay in `assets/`; docs retain concise original analysis and references to payload hashes.
|
| 54 |
|
| 55 |
## Investigation sequence
|
| 56 |
|
docs/TODO.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
| 1 |
# Exhaustive work list
|
| 2 |
|
| 3 |
-
Baseline: 2026-10-21. The setup and extraction implementation is complete; checked items are verified in [SETUP.md](SETUP.md). The single-repository layout supersedes the initial separate-dataset proposal. Findings F01–
|
| 4 |
|
| 5 |
Each task ID is stable. Split tasks into child IDs as evidence grows. Record dependencies, output documents/code, validation evidence, and remaining limitations when checking a task off. New discoveries extend this list. P0–P2 establish preservation; P3–P9 establish behavioral contracts; P10–P16 implement and prove the rewrite. P10's GPU spike should happen early alongside source research, before renderer architecture is locked.
|
| 6 |
|
|
@@ -16,7 +16,7 @@ Each task ID is stable. Split tasks into child IDs as evidence grows. Record dep
|
|
| 16 |
- [ ] P0.06 Resolve the absent font license notice and actual font origin; plan a newly licensed replacement if necessary.
|
| 17 |
- [ ] P0.07 Choose the rewrite's source license and attribution policy without applying it to preserved reference content.
|
| 18 |
- [ ] P0.08 Define the compatibility surface for bundled plugins, third-party IXPL source, compiled plugins, and experimental tools; carry all undecided surfaces as open tasks.
|
| 19 |
-
- [
|
| 20 |
- [ ] P0.10 Record supported reference behaviors versus intentionally improved behavior, including lossy imports and historical bugs, in a parity matrix.
|
| 21 |
|
| 22 |
## P1 — Git, Hugging Face, direnv, and Nix
|
|
@@ -58,7 +58,7 @@ Each task ID is stable. Split tasks into child IDs as evidence grows. Record dep
|
|
| 58 |
- [x] P2.08 Preserve raw bytes and filenames; record timestamps/attributes separately when host filesystems cannot preserve them; document newline/encoding observations without silently normalizing originals.
|
| 59 |
- [x] P2.09 Make extraction idempotent; detect modified destinations, stale outputs, truncated runs, disk-space errors, and concurrent invocations. Never overwrite user work through an implicit force mode.
|
| 60 |
- [x] P2.10 Write machine-readable inventories containing archive identity, path, size, SHA256, ZIP CRC/attributes, classification, version, provenance, and extraction tool version.
|
| 61 |
-
- [ ] P2.11 Generate cross-version rename/copy/change candidates and a resource dependency graph; keep byte identity separate from semantic similarity.
|
| 62 |
- [ ] P2.12 Test adversarial archives and repeat extraction on macOS/Linux; compare output hashes and member sets to the inventories.
|
| 63 |
- [x] P2.13 Ignore disposable local runtime/build workspaces and extraction locks/temporaries; reserve separate asset paths for future derivatives, fixtures, and captures.
|
| 64 |
- [x] P2.14 Document complete regeneration from original archives and asset revision, including offline operation.
|
|
@@ -67,9 +67,9 @@ Each task ID is stable. Split tasks into child IDs as evidence grows. Record dep
|
|
| 67 |
|
| 68 |
**Depends on:** P0 permissions for the chosen activities, P2 references. **Exit:** reproducible observation or explicitly bounded alternatives for every unavailable oracle.
|
| 69 |
|
| 70 |
-
- [
|
| 71 |
- [ ] P3.02 Turn the member inventory into a coverage ledger, with a disposition and investigation owner for every file and discovered external dependency.
|
| 72 |
-
- [ ] P3.03 Index all plugins, includes, interrupts, commands, callbacks, configuration keys, settings, localization keys, shader uniforms, and file-format rules with source anchors.
|
| 73 |
- [ ] P3.04 Build a versioned include/call/resource graph; identify host-only operations and code shared between plugins.
|
| 74 |
- [ ] P3.05 Prepare a documented Windows x86-compatible VM oracle; investigate a separate Linux/Wine oracle if useful. Pin OS/toolchain/drivers/prefix details and snapshot clean state.
|
| 75 |
- [ ] P3.06 Inventory executable imports/resources/CLR metadata and runtime requirements using activities permitted under P0; distinguish native editor and managed tools.
|
|
@@ -78,11 +78,13 @@ Each task ID is stable. Split tasks into child IDs as evidence grows. Record dep
|
|
| 78 |
- [ ] P3.09 Verify plugin/model builds and launch every version; record failures and their boundaries rather than asserting the latest cannot work from one machine.
|
| 79 |
- [ ] P3.10 Create an oracle runner for documented compiler/converter commands and controlled UI replay; collect deterministic IDs and scrub only explicitly nondeterministic metadata.
|
| 80 |
- [ ] P3.11 Capture screenshots/video, interaction traces, filesystem diffs, timing, errors, and process/dependency logs as asset payloads with textual summaries in docs.
|
| 81 |
-
- [
|
| 82 |
- [ ] P3.13 Recover additional manuals/tutorials/videos/sample projects and trace their provenance; track MB2 binaries/C# converters as a separate optional recovery stream, without claiming MB3 is MB2.
|
| 83 |
- [ ] P3.14 If permitted binary work is needed, index relevant routines/managed methods, call graphs, data structures, serializers, and host API handlers; link every conclusion to offsets/tokens and the exact binary hash.
|
| 84 |
- [ ] P3.15 Reconcile source, runtime, older versions, and binary evidence; document contradictions and minimal counterexamples.
|
| 85 |
|
|
|
|
|
|
|
| 86 |
## P4 — IXPL, host APIs, plugins, and auxiliary tools
|
| 87 |
|
| 88 |
**Depends on:** P3 indexing; oracle-dependent tasks use P3 runtime. **Exit:** every exposed host operation and bundled module has a behavior contract and rewrite disposition.
|
|
@@ -100,6 +102,9 @@ Each task ID is stable. Split tasks into child IDs as evidence grows. Record dep
|
|
| 100 |
- [ ] P4.11 If IXPL execution is required, separately plan parser/type checker/runtime or translation, host capability boundaries, diagnostics, resource limits, migration tools, and conformance tests; do not load arbitrary legacy plugins into the Rust host by default.
|
| 101 |
- [ ] P4.12 Account for all three auxiliary executable roles and all 17 BAT files with native command replacements or a documented reference-only disposition.
|
| 102 |
|
|
|
|
|
|
|
|
|
|
| 103 |
## P5 — World representation and geometry kernel
|
| 104 |
|
| 105 |
**Depends on:** P4 API contracts; feeds P7 tools and P6 formats. **Exit:** geometry specification plus analytic/reference fixtures and numerical policies.
|
|
@@ -140,6 +145,8 @@ Each task ID is stable. Split tasks into child IDs as evidence grows. Record dep
|
|
| 140 |
- [ ] P6.15 Implement safe Rust parsers/writers and native `inspect/validate/convert` CLI; fuzz parsers, bound allocation/recursion, and test all supported round trips.
|
| 141 |
- [ ] P6.16 Verify output interoperability with independent consumers where available, alongside reference-compatible results; separate intentional improvements from differences that indicate bugs.
|
| 142 |
|
|
|
|
|
|
|
| 143 |
## P7 — Input, cameras, grids, views, and editing workflows
|
| 144 |
|
| 145 |
**Depends on:** P4 dispatch and P5 geometry. **Exit:** complete interaction/state-machine specifications and reproducible replays.
|
|
@@ -299,4 +306,4 @@ Each task ID is stable. Split tasks into child IDs as evidence grows. Record dep
|
|
| 299 |
| M6 Full reconstruction | All required P12/P13 modules and workflows pass parity and GPU checks |
|
| 300 |
| M7 Distributable release | P14–P16 regeneration, packaging, documentation, clean-machine acceptance |
|
| 301 |
|
| 302 |
-
Next work after
|
|
|
|
| 1 |
# Exhaustive work list
|
| 2 |
|
| 3 |
+
Baseline: 2026-10-21. The setup and extraction implementation is complete; checked items are verified in [SETUP.md](SETUP.md). The single-repository layout supersedes the initial separate-dataset proposal. Findings F01–F23 are in [FINDINGS.md](FINDINGS.md). The [investigation method](REVERSE_ENGINEERING.md) defines evidence requirements; [technical direction](TECHNICAL_DIRECTION.md) describes proposed boundaries.
|
| 4 |
|
| 5 |
Each task ID is stable. Split tasks into child IDs as evidence grows. Record dependencies, output documents/code, validation evidence, and remaining limitations when checking a task off. New discoveries extend this list. P0–P2 establish preservation; P3–P9 establish behavioral contracts; P10–P16 implement and prove the rewrite. P10's GPU spike should happen early alongside source research, before renderer architecture is locked.
|
| 6 |
|
|
|
|
| 16 |
- [ ] P0.06 Resolve the absent font license notice and actual font origin; plan a newly licensed replacement if necessary.
|
| 17 |
- [ ] P0.07 Choose the rewrite's source license and attribution policy without applying it to preserved reference content.
|
| 18 |
- [ ] P0.08 Define the compatibility surface for bundled plugins, third-party IXPL source, compiled plugins, and experimental tools; carry all undecided surfaces as open tasks.
|
| 19 |
+
- [x] P0.09 Open a risk/decision register for unavailable MB2, missing source, unavailable oracle, resource gaps, and GPU restrictions; give each risk an owner and a next experiment.
|
| 20 |
- [ ] P0.10 Record supported reference behaviors versus intentionally improved behavior, including lossy imports and historical bugs, in a parity matrix.
|
| 21 |
|
| 22 |
## P1 — Git, Hugging Face, direnv, and Nix
|
|
|
|
| 58 |
- [x] P2.08 Preserve raw bytes and filenames; record timestamps/attributes separately when host filesystems cannot preserve them; document newline/encoding observations without silently normalizing originals.
|
| 59 |
- [x] P2.09 Make extraction idempotent; detect modified destinations, stale outputs, truncated runs, disk-space errors, and concurrent invocations. Never overwrite user work through an implicit force mode.
|
| 60 |
- [x] P2.10 Write machine-readable inventories containing archive identity, path, size, SHA256, ZIP CRC/attributes, classification, version, provenance, and extraction tool version.
|
| 61 |
+
- [ ] P2.11 Generate cross-version rename/copy/change candidates and a resource dependency graph; keep byte identity separate from semantic similarity. Initial hash/include/literal-resource graph is in E01; implicit/dynamic resource semantics and semantic version comparisons remain open.
|
| 62 |
- [ ] P2.12 Test adversarial archives and repeat extraction on macOS/Linux; compare output hashes and member sets to the inventories.
|
| 63 |
- [x] P2.13 Ignore disposable local runtime/build workspaces and extraction locks/temporaries; reserve separate asset paths for future derivatives, fixtures, and captures.
|
| 64 |
- [x] P2.14 Document complete regeneration from original archives and asset revision, including offline operation.
|
|
|
|
| 67 |
|
| 68 |
**Depends on:** P0 permissions for the chosen activities, P2 references. **Exit:** reproducible observation or explicitly bounded alternatives for every unavailable oracle.
|
| 69 |
|
| 70 |
+
- [x] P3.01 Establish findings/specifications/experiments/decisions/parity/validation documents with stable IDs and the evidence schema in `REVERSE_ENGINEERING.md`.
|
| 71 |
- [ ] P3.02 Turn the member inventory into a coverage ledger, with a disposition and investigation owner for every file and discovered external dependency.
|
| 72 |
+
- [ ] P3.03 Index all plugins, includes, interrupts, commands, callbacks, configuration keys, settings, localization keys, shader uniforms, and file-format rules with source anchors. E01 covers source includes/Core/tool registrations, grammar rules, literal CFG declarations and shader uniforms; full consumer/dynamic keys and localization still need investigation.
|
| 73 |
- [ ] P3.04 Build a versioned include/call/resource graph; identify host-only operations and code shared between plugins.
|
| 74 |
- [ ] P3.05 Prepare a documented Windows x86-compatible VM oracle; investigate a separate Linux/Wine oracle if useful. Pin OS/toolchain/drivers/prefix details and snapshot clean state.
|
| 75 |
- [ ] P3.06 Inventory executable imports/resources/CLR metadata and runtime requirements using activities permitted under P0; distinguish native editor and managed tools.
|
|
|
|
| 78 |
- [ ] P3.09 Verify plugin/model builds and launch every version; record failures and their boundaries rather than asserting the latest cannot work from one machine.
|
| 79 |
- [ ] P3.10 Create an oracle runner for documented compiler/converter commands and controlled UI replay; collect deterministic IDs and scrub only explicitly nondeterministic metadata.
|
| 80 |
- [ ] P3.11 Capture screenshots/video, interaction traces, filesystem diffs, timing, errors, and process/dependency logs as asset payloads with textual summaries in docs.
|
| 81 |
+
- [x] P3.12 Define oracle availability labels: reproduced, source-only, historical report, inferred, unavailable; keep unverified tasks open if startup cannot be restored.
|
| 82 |
- [ ] P3.13 Recover additional manuals/tutorials/videos/sample projects and trace their provenance; track MB2 binaries/C# converters as a separate optional recovery stream, without claiming MB3 is MB2.
|
| 83 |
- [ ] P3.14 If permitted binary work is needed, index relevant routines/managed methods, call graphs, data structures, serializers, and host API handlers; link every conclusion to offsets/tokens and the exact binary hash.
|
| 84 |
- [ ] P3.15 Reconcile source, runtime, older versions, and binary evidence; document contradictions and minimal counterexamples.
|
| 85 |
|
| 86 |
+
- [x] P3.16 Generate a verified static index across all five builds: file coverage/follow-ups, include candidates, qualified calls, constant/wrapper mappings, tool/resource expressions and reproducible report/index outputs (E01).
|
| 87 |
+
|
| 88 |
## P4 — IXPL, host APIs, plugins, and auxiliary tools
|
| 89 |
|
| 90 |
**Depends on:** P3 indexing; oracle-dependent tasks use P3 runtime. **Exit:** every exposed host operation and bundled module has a behavior contract and rewrite disposition.
|
|
|
|
| 102 |
- [ ] P4.11 If IXPL execution is required, separately plan parser/type checker/runtime or translation, host capability boundaries, diagnostics, resource limits, migration tools, and conformance tests; do not load arbitrary legacy plugins into the Rust host by default.
|
| 103 |
- [ ] P4.12 Account for all three auxiliary executable roles and all 17 BAT files with native command replacements or a documented reference-only disposition.
|
| 104 |
|
| 105 |
+
- [x] P4.13 Resolve and document the source-declared Core interrupt ranges and all latest wrappers, with version comparisons and explicit ABI/context limits (F21).
|
| 106 |
+
- [x] P4.14 Map every top-level/experimental plugin and nine named task clients, including registrations, message shapes and source-level lifecycle risks (F23).
|
| 107 |
+
|
| 108 |
## P5 — World representation and geometry kernel
|
| 109 |
|
| 110 |
**Depends on:** P4 API contracts; feeds P7 tools and P6 formats. **Exit:** geometry specification plus analytic/reference fixtures and numerical policies.
|
|
|
|
| 145 |
- [ ] P6.15 Implement safe Rust parsers/writers and native `inspect/validate/convert` CLI; fuzz parsers, bound allocation/recursion, and test all supported round trips.
|
| 146 |
- [ ] P6.16 Verify output interoperability with independent consumers where available, alongside reference-compatible results; separate intentional improvements from differences that indicate bugs.
|
| 147 |
|
| 148 |
+
- [x] P6.17 Document the initial grammar/writer format map and source discrepancies, keeping MB3 DAT, IXModel and plugin artifacts distinct (F15–F20).
|
| 149 |
+
|
| 150 |
## P7 — Input, cameras, grids, views, and editing workflows
|
| 151 |
|
| 152 |
**Depends on:** P4 dispatch and P5 geometry. **Exit:** complete interaction/state-machine specifications and reproducible replays.
|
|
|
|
| 306 |
| M6 Full reconstruction | All required P12/P13 modules and workflows pass parity and GPU checks |
|
| 307 |
| M7 Distributable release | P14–P16 regeneration, packaging, documentation, clean-machine acceptance |
|
| 308 |
|
| 309 |
+
Next work after the source map: establish a runtime oracle (P3.05–P3.10), derive consumer/dynamic config and localization keys (P3.03), validate format semantics/MB3 DAT (P6), and continue P2.11 resource/semantic version analysis. The synthetic P10 rendering spike remains independent. Linux extraction/runtime validation remains open in P2.12. Treat M2 and M3 as separate gates; source investigation can proceed while GPU work is unresolved.
|
docs/decisions/D01-source-mapping.md
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# D01 — Source mapping before runtime contracts
|
| 2 |
+
|
| 3 |
+
Date: 2026-10-21. Status: adopted for the current investigation. Basis: the user's request to start mapping the extracted formats/plugins/APIs/dependencies and the supplied readable sources.
|
| 4 |
+
|
| 5 |
+
Use hash-verified, static source evidence first. Preserve binary/reference inputs; generate raw machine indexes under Xet-filtered assets and keep authored interpretation/index documents under docs. Classify declarations, writer implementations and historical/runtime claims separately. A lexical call/include edge is a candidate dependency, not a demonstrated execution path.
|
| 6 |
+
|
| 7 |
+
This decision does not select a Rust plugin ABI, implement a legacy VM, choose a license, or resolve executable investigation permissions. It keeps broader parity tasks open and provides concrete next experiments from the source map. E01 and F15–F23 record this stage's evidence.
|
docs/experiments/static-map-2026-10-21.md
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# E01 — Static reference mapping
|
| 2 |
+
|
| 3 |
+
Date: 2026-10-21. Status: **source-only, reproduced static analysis**. Reference code was not executed.
|
| 4 |
+
|
| 5 |
+
## Inputs and procedure
|
| 6 |
+
|
| 7 |
+
All five original ZIP identities are pinned in `config/references.json`. Every archive is rechecked against its original size/SHA-256 and member CRCs; all extracted files are compared to archive-member hashes before indexing. Source paths and full hashes remain in the generated report. The report also records the generator's own SHA-256.
|
| 8 |
+
|
| 9 |
+
From the repository root:
|
| 10 |
+
|
| 11 |
+
```sh
|
| 12 |
+
nix develop --command python3 scripts/map_references.py
|
| 13 |
+
nix develop --command python3 scripts/map_references.py --check
|
| 14 |
+
nix develop --command python3 scripts/test_setup.py
|
| 15 |
+
```
|
| 16 |
+
|
| 17 |
+
The indexer tokenizes IXPL strings/comments, collects include candidates, evaluates a restricted integer-expression subset, associates interrupt wrappers with source signatures, resolves unambiguous tool-name concatenations, and inventories config declarations, grammar rules, shader sections/uniforms, batch text and resource candidates. Adjacent builds are compared by file hashes. No parser/compiler/plugin/EXE is launched.
|
| 18 |
+
|
| 19 |
+
## Outputs and observations
|
| 20 |
+
|
| 21 |
+
- `assets/analysis/source-map.json`: reproducible full per-build evidence and initial file coverage ledger; Xet payload.
|
| 22 |
+
- `docs/API_INDEX.md`: latest 408 Core endpoints and source wrapper anchors; ordinary authored/generated documentation.
|
| 23 |
+
- `docs/PLUGIN_INDEX.md`: 201 literal-resolved plugin `initTool` call sites; ordinary documentation.
|
| 24 |
+
- Five builds, 560 regular-member occurrences, 47 latest IXPL files, 487 include directives across all builds; no missing/ambiguous include candidate sets under the documented search policy.
|
| 25 |
+
- Latest host intervals resolve to 0–248, 249–333, 334–404, and 405–407. Every Core interrupt wrapper has a matching same-line function signature; no unresolved Core constant expression remains.
|
| 26 |
+
- 40 literal typed CFG declaration records are indexed. This is not a complete consumer config-key inventory: scope-derived/dynamic keys and string tables require further work.
|
| 27 |
+
|
| 28 |
+
## Controls and limitations
|
| 29 |
+
|
| 30 |
+
Synthetic tests cover fake dependencies in comments/ordinary/delimiter strings, nested call arguments, overload/source anchors, restricted constant evaluation, ambiguous/cyclic string bindings, long literal blocks, missing/ambiguous includes, modified input hashes, and copy/rename distinctions. They run without original assets.
|
| 31 |
+
|
| 32 |
+
The mapper is a lexical index, not an IXPL compiler, whole-program type/call analysis, runtime tracer, or format decoder. Parenthesis/array/brace argument structure is recognized; generic angle-bracket type expressions are not a full grammar. Include ordering, callback reachability, implicit host paths, dynamic strings and source/runtime discrepancies remain open.
|
| 33 |
+
|
| 34 |
+
No runtime oracle is available in this experiment. Historical reports, source comments, writer implementations and measured host behavior retain separate labels as defined in REVERSE_ENGINEERING.md. “Unavailable here” does not establish that an executable cannot be made to run.
|
docs/parity.md
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Reference coverage ledger
|
| 2 |
+
|
| 3 |
+
Initial source coverage, 2026-10-21. Owner for this ledger and the external dependencies listed in [DEPENDENCIES.md](DEPENDENCIES.md): **Nanobrush reference research**. No runtime or Rust parity is claimed.
|
| 4 |
+
|
| 5 |
+
Every one of the 560 regular-member occurrences has its own path/hash/category/coverage/owner/follow-up entry in [source-map.json](../assets/analysis/source-map.json). Direct include candidates, qualified calls, interrupt wrappers, tool registrations and literal-resource candidates remain attached to their source file. The human documents summarize behavior without copying the raw reference tree into ordinary Git.
|
| 6 |
+
|
| 7 |
+
| Latest-build category | Files | Initial disposition | Next contract/validation task |
|
| 8 |
+
| --- | ---: | --- | --- |
|
| 9 |
+
| Core host includes | 5 | Source-indexed; native contract/adapter planned | P4.03, P3.14 host behavior |
|
| 10 |
+
| Task clients | 9 | Source-indexed; service/protocol contracts planned | P4.05 |
|
| 11 |
+
| Top-level plugins | 17 | Source-indexed; native functionality planned | P4.08, P7 |
|
| 12 |
+
| Experimental plugins | 5 | Source-indexed; equivalent functionality or explicit scope decision required | P4.09 |
|
| 13 |
+
| IXPL utilities/misc | 10 | Source-indexed; needed functionality requires independent port | P4.07 |
|
| 14 |
+
| Model generator | 1 | Source-indexed; native generation target | P9.06 |
|
| 15 |
+
| Grammars | 7 | Grammar rules indexed; initial format map written | P6.01–P6.10 |
|
| 16 |
+
| CFG resources | 15 | Literal typed declarations indexed; full consumer semantics pending | P8.09 |
|
| 17 |
+
| Shader containers | 3 | Sections/uniforms indexed; selected output expressions reviewed | P9.01–P9.04 |
|
| 18 |
+
| BAT files | 17 | Text inventory and build/conversion boundary reviewed | P4.12 |
|
| 19 |
+
| Images | 4 | Byte inventory only in this pass; provenance/atlas meaning pending | P9.05 |
|
| 20 |
+
| Executables | 3 | Byte inventory only; native/managed classification from earlier header inspection | P3.06 |
|
| 21 |
+
| Other reference text | 28 | Encoding/line inventory; selected readmes/help reviewed | P3.02; original licenses P0.04 |
|
| 22 |
+
| Total | 124 | All regular members accounted for | No category has complete runtime parity |
|
| 23 |
+
|
| 24 |
+
“Lexically indexed” means identifiers/edges can be located, not that a complete language parser or host implementation is understood. “Text inventoried” means text identity/encoding/lines are known; it does not mean every paragraph has been semantically reviewed. CP1252 fallback is a decoding choice for indexing, not a proven application encoding contract.
|
| 25 |
+
|
| 26 |
+
## Remaining mapping gaps
|
| 27 |
+
|
| 28 |
+
- Complete consumer-derived config keys, dotted scope handling, localized string tables and dynamic key generation.
|
| 29 |
+
- Dynamic file/resource names, implicit loader conventions, and actual compiler include precedence.
|
| 30 |
+
- Static and dynamic plugin load/unload order, callback concurrency, task priority ordering and errors.
|
| 31 |
+
- Primitive serialization widths/encoding, MB3 DAT layout, compiled plugin representation and runtime dependencies.
|
| 32 |
+
- Full tool state machines, geometry algorithms/tolerances, shader bindings and file-conversion preservation.
|
| 33 |
+
- Source discrepancies versus executed behavior; no original executable was run in this pass.
|
| 34 |
+
|
| 35 |
+
Keep the broad parent TODO tasks open until their promised behavioral evidence exists. The completed source-mapping subtasks record this pass without marking an entire subsystem reverse engineered.
|
docs/risks.md
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Research risks and next evidence
|
| 2 |
+
|
| 3 |
+
Opened 2026-10-21. Owner: Nanobrush reference research. This register tracks concrete gaps; none of these entries alone blocks the source mapping already authorized by the user.
|
| 4 |
+
|
| 5 |
+
| ID | Evidence/gap | Impact | Next experiment/task |
|
| 6 |
+
| --- | --- | --- | --- |
|
| 7 |
+
| R01 | Original editor/engine source absent | Host implementations and runtime contracts remain unknown | Establish oracle and identify host boundaries, P3.05–P3.14 |
|
| 8 |
+
| R02 | Actual archive terms restrict executable RE/reuse/redistribution | Investigation/distribution paths need their own recorded basis | P0.04/P0.05; preserved original texts |
|
| 9 |
+
| R03 | No MB2 binary or converter sources recovered | Cannot claim MB2 compatibility | Optional P3.13 recovery stream |
|
| 10 |
+
| R04 | Missing font notice and unresolved resource naming | Runtime asset reuse and startup behavior remain uncertain | P0.06/P8.07/P8.08 |
|
| 11 |
+
| R05 | MB3 DAT byte layout and plugin representation unknown | No compatible native codec/runtime yet | Controlled fixtures, P6.03/P6.09 |
|
| 12 |
+
| R06 | Core IDs and IXModel versions change across builds | Misinterpreted older artifacts if latest tables are reused | Version-specific experiments, P4.03/P6.08 |
|
| 13 |
+
| R07 | Grammars and APIs do not prove semantic preservation | Risk of lossy or incorrect import/save | Format matrix/loss reports, P6.11/P6.13 |
|
| 14 |
+
| R08 | Single mutable callback slots and cached failed service lookups | Potential concurrency/order bugs | P4.04/P4.05 targeted task experiments |
|
| 15 |
+
| R09 | IXModel reset writer and file-stack inconsistencies | Source-derived decoder could encode the wrong behavior | Generate nested-handle/reset fixtures, P6.08 |
|
| 16 |
+
| R10 | Raycast helper temporarily changes selection | A pure Rust ray query may differ in observable callbacks/state | P5.06/P7.11 replay fixture |
|
| 17 |
+
| R11 | No executed oracle in this pass | Source-backed findings cannot be labelled runtime verified | P3.05–P3.12 |
|
| 18 |
+
| R12 | Solari/backend/platform qualification still open | Platform goal depends on measured hardware support | Synthetic P10 spike independent of these references |
|
| 19 |
+
| R13 | Static index deliberately lacks full IXPL typing/control-flow | Lexical edge/registration counts can overstate live behavior | Preserve uncertainty; refine analysis and compare actual traces |
|
docs/validation.md
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Validation ledger
|
| 2 |
+
|
| 3 |
+
## Setup baseline
|
| 4 |
+
|
| 5 |
+
See [SETUP.md](SETUP.md) for Nix/direnv, Xet upload/recovery, preservation checks and the original 28 setup regressions. Linux and Intel macOS execution remain unverified.
|
| 6 |
+
|
| 7 |
+
## E01 source mapping — 2026-10-21
|
| 8 |
+
|
| 9 |
+
See [the experiment](experiments/static-map-2026-10-21.md) for commands, scope and limitations. The static scanner adds nine synthetic regressions, bringing the combined suite to 37. Full-corpus checks additionally revalidate five archives/all extracted file hashes, resolve every Core constant, require a matching wrapper signature for all Core interrupt sites, check include candidate closure, and compare generated indexes against report identities.
|
| 10 |
+
|
| 11 |
+
Code-only tests do not need original assets. The full `map_references.py --check` command requires hydrated references and checks reproducibility of the Xet report and both generated Markdown indexes.
|
| 12 |
+
|
| 13 |
+
Host synthetic suite: 37 passed; the code-only Apple Silicon Nix check also built successfully with all 37 tests. The Nix `check-reference-map` command passed against the hydrated corpus. Full report/index regeneration followed by --check passed. All 560 extracted inputs were hash-verified; 487 include candidates and every Core declaration/wrapper across five builds satisfied the closure checks. A historical Brush-return signature case has its own regression.
|
| 14 |
+
|
| 15 |
+
The current results establish static mapping only. No runtime API contract, format round trip, editor workflow, executable startup, graphics compatibility or Rust parity is established by E01.
|
flake.nix
CHANGED
|
@@ -89,6 +89,8 @@
|
|
| 89 |
verify-references = command "scripts/references.py verify";
|
| 90 |
unpack-references = command "scripts/references.py unpack";
|
| 91 |
index-references = command "scripts/references.py index";
|
|
|
|
|
|
|
| 92 |
test-setup = command "scripts/test_setup.py";
|
| 93 |
check-environment = command "scripts/check_environment.py";
|
| 94 |
};
|
|
|
|
| 89 |
verify-references = command "scripts/references.py verify";
|
| 90 |
unpack-references = command "scripts/references.py unpack";
|
| 91 |
index-references = command "scripts/references.py index";
|
| 92 |
+
map-references = command "scripts/map_references.py";
|
| 93 |
+
check-reference-map = command "scripts/map_references.py --check";
|
| 94 |
test-setup = command "scripts/test_setup.py";
|
| 95 |
check-environment = command "scripts/check_environment.py";
|
| 96 |
};
|
scripts/map_references.py
ADDED
|
@@ -0,0 +1,413 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#!/usr/bin/env python3
|
| 2 |
+
"""Deterministic static IXPL/resource index; does not compile or execute references."""
|
| 3 |
+
import argparse
|
| 4 |
+
import ast
|
| 5 |
+
from collections import Counter, defaultdict
|
| 6 |
+
import hashlib
|
| 7 |
+
import json
|
| 8 |
+
from pathlib import Path, PurePosixPath
|
| 9 |
+
import re
|
| 10 |
+
import sys
|
| 11 |
+
|
| 12 |
+
import references
|
| 13 |
+
|
| 14 |
+
ROOT = Path(__file__).resolve().parents[1]
|
| 15 |
+
OUT = ROOT / 'assets/analysis/source-map.json'
|
| 16 |
+
TEXT_SUFFIXES = {'.ixpl', '.txt', '.cfg', '.shader', '.bat'}
|
| 17 |
+
|
| 18 |
+
|
| 19 |
+
def lex(source):
|
| 20 |
+
"""Return offset/line-preserving tokens; comments disappear, strings stay opaque.
|
| 21 |
+
|
| 22 |
+
IXPL delimiter strings (backslash quote delimiter ... delimiter quote) may
|
| 23 |
+
contain arbitrary multiline text. This is a source index, not an IXPL parser.
|
| 24 |
+
"""
|
| 25 |
+
tokens = []
|
| 26 |
+
i, line = 0, 1
|
| 27 |
+
while i < len(source):
|
| 28 |
+
start, begin = i, line
|
| 29 |
+
c = source[i]
|
| 30 |
+
if c.isspace():
|
| 31 |
+
line += c == '\n'
|
| 32 |
+
i += 1
|
| 33 |
+
continue
|
| 34 |
+
if source.startswith('//', i):
|
| 35 |
+
end = source.find('\n', i)
|
| 36 |
+
i = len(source) if end < 0 else end
|
| 37 |
+
continue
|
| 38 |
+
if source.startswith('/*', i):
|
| 39 |
+
end = source.find('*/', i + 2)
|
| 40 |
+
if end < 0:
|
| 41 |
+
raise ValueError(f'Unterminated comment at line {line}')
|
| 42 |
+
i = end + 2
|
| 43 |
+
line += source[start:i].count('\n')
|
| 44 |
+
continue
|
| 45 |
+
if source.startswith('\\"', i):
|
| 46 |
+
if i + 2 >= len(source):
|
| 47 |
+
raise ValueError(f'Incomplete delimiter string at line {line}')
|
| 48 |
+
delimiter = source[i + 2]
|
| 49 |
+
closing = {'[': ']', '{': '}', '(': ')', '<': '>'}.get(delimiter, delimiter) + '"'
|
| 50 |
+
end = source.find(closing, i + 3)
|
| 51 |
+
if end < 0:
|
| 52 |
+
raise ValueError(f'Unterminated delimiter string at line {line}')
|
| 53 |
+
i = end + 2
|
| 54 |
+
kind = 'string'
|
| 55 |
+
elif c in '\"\'':
|
| 56 |
+
i += 1
|
| 57 |
+
while i < len(source):
|
| 58 |
+
if source[i] == '\\':
|
| 59 |
+
i += 2
|
| 60 |
+
elif source[i] == c:
|
| 61 |
+
i += 1
|
| 62 |
+
break
|
| 63 |
+
else:
|
| 64 |
+
i += 1
|
| 65 |
+
else:
|
| 66 |
+
raise ValueError(f'Unterminated quoted literal at line {line}')
|
| 67 |
+
kind = 'string' if c == '"' else 'char'
|
| 68 |
+
elif c.isalpha() or c in '_$@':
|
| 69 |
+
i += 1
|
| 70 |
+
while i < len(source) and (source[i].isalnum() or source[i] in '_$'):
|
| 71 |
+
i += 1
|
| 72 |
+
kind = 'identifier'
|
| 73 |
+
elif c.isdigit():
|
| 74 |
+
i += 1
|
| 75 |
+
while i < len(source) and (source[i].isalnum() or source[i] == '.'):
|
| 76 |
+
i += 1
|
| 77 |
+
kind = 'number'
|
| 78 |
+
else:
|
| 79 |
+
i += 2 if source[i:i+2] in ('::', '+=', '==', '!=', '@=', '<=', '>=') else 1
|
| 80 |
+
kind = 'symbol'
|
| 81 |
+
tokens.append({'kind': kind, 'text': source[start:i], 'offset': start, 'end': i, 'line': begin})
|
| 82 |
+
line += source[start:i].count('\n')
|
| 83 |
+
return tokens
|
| 84 |
+
|
| 85 |
+
|
| 86 |
+
def masked(source, tokens):
|
| 87 |
+
result = list(source)
|
| 88 |
+
for i, c in enumerate(source):
|
| 89 |
+
if c not in '\r\n':
|
| 90 |
+
result[i] = ' '
|
| 91 |
+
for token in tokens:
|
| 92 |
+
if token['kind'] not in ('string', 'char'):
|
| 93 |
+
result[token['offset']:token['end']] = source[token['offset']:token['end']]
|
| 94 |
+
return ''.join(result)
|
| 95 |
+
|
| 96 |
+
|
| 97 |
+
def arguments(tokens, opening):
|
| 98 |
+
"""Split a call's balanced parentheses/arrays/braces, without parsing types."""
|
| 99 |
+
stack, values, start = [], [], opening + 1
|
| 100 |
+
pairs = {')': '(', ']': '[', '}': '{'}
|
| 101 |
+
for i in range(opening, len(tokens)):
|
| 102 |
+
t = tokens[i]['text'] if tokens[i]['kind'] == 'symbol' else ''
|
| 103 |
+
if t in ('(', '[', '{'):
|
| 104 |
+
stack.append(t)
|
| 105 |
+
elif t in pairs:
|
| 106 |
+
if not stack or stack[-1] != pairs[t]:
|
| 107 |
+
raise ValueError(f'Unbalanced call at line {tokens[opening]["line"]}')
|
| 108 |
+
stack.pop()
|
| 109 |
+
if not stack:
|
| 110 |
+
if i > start:
|
| 111 |
+
values.append(tokens[start:i])
|
| 112 |
+
return values, i
|
| 113 |
+
elif t == ',' and len(stack) == 1:
|
| 114 |
+
values.append(tokens[start:i]); start = i + 1
|
| 115 |
+
raise ValueError(f'Unterminated call at line {tokens[opening]["line"]}')
|
| 116 |
+
|
| 117 |
+
|
| 118 |
+
def text_of(source, tokens):
|
| 119 |
+
return source[tokens[0]['offset']:tokens[-1]['end']] if tokens else ''
|
| 120 |
+
|
| 121 |
+
|
| 122 |
+
def constant_value(expression, values):
|
| 123 |
+
node = ast.parse(expression, mode='eval').body
|
| 124 |
+
def visit(n):
|
| 125 |
+
if isinstance(n, ast.Constant) and type(n.value) is int:
|
| 126 |
+
return n.value
|
| 127 |
+
if isinstance(n, ast.Name) and n.id in values:
|
| 128 |
+
return values[n.id]
|
| 129 |
+
if isinstance(n, ast.UnaryOp) and isinstance(n.op, (ast.UAdd, ast.USub)):
|
| 130 |
+
return visit(n.operand) * (-1 if isinstance(n.op, ast.USub) else 1)
|
| 131 |
+
if isinstance(n, ast.BinOp) and isinstance(n.op, (ast.Add, ast.Sub)):
|
| 132 |
+
return visit(n.left) + (visit(n.right) if isinstance(n.op, ast.Add) else -visit(n.right))
|
| 133 |
+
raise ValueError('Unsupported or unresolved constant expression')
|
| 134 |
+
return visit(node)
|
| 135 |
+
|
| 136 |
+
|
| 137 |
+
def scan_ixpl(source):
|
| 138 |
+
tokens = lex(source)
|
| 139 |
+
code = masked(source, tokens)
|
| 140 |
+
aliases = dict(re.findall(r'\bnamespace\s+(\w+)\s*=\s*(\w+)\s*;', code))
|
| 141 |
+
constants = []
|
| 142 |
+
for m in re.finditer(r'\b((?:_?INT_\w+|CMD_\w+|coreVersion|akulaCoreVersion))\s*=\s*([^,;\r\n]+)', code):
|
| 143 |
+
constants.append({'name': m[1], 'expression': m[2].strip(), 'line': source.count('\n', 0, m.start(1)) + 1})
|
| 144 |
+
calls = []
|
| 145 |
+
for i, token in enumerate(tokens[:-1]):
|
| 146 |
+
if token['kind'] != 'identifier' or tokens[i+1]['text'] != '(':
|
| 147 |
+
continue
|
| 148 |
+
qualified = i >= 2 and tokens[i-1]['text'] == '::'
|
| 149 |
+
if not qualified and token['text'] != 'interrupt':
|
| 150 |
+
continue
|
| 151 |
+
args, end = arguments(tokens, i+1)
|
| 152 |
+
qualifier = tokens[i-2]['text'] if qualified else None
|
| 153 |
+
calls.append({'qualifier': aliases.get(qualifier, qualifier), 'method': token['text'],
|
| 154 |
+
'line': token['line'], 'offset': token['offset'],
|
| 155 |
+
'arguments': [text_of(source, a) for a in args]})
|
| 156 |
+
includes = [{'include': m[1], 'line': source.count('\n', 0, m.start(1)) + 1}
|
| 157 |
+
for m in re.finditer(r'^[ \t]*#[ \t]*include[ \t]+"([^"\r\n]+)"', source, re.M)
|
| 158 |
+
if any(t['text'] == '#' and t['offset'] <= m.start(1) and source.count('\n',0,t['offset']) + 1 == source.count('\n',0,m.start(1)) + 1 for t in tokens)]
|
| 159 |
+
# Source-level wrappers, with complete balanced signatures (including tuple args).
|
| 160 |
+
headers = []
|
| 161 |
+
token_offsets = {t['offset']:i for i,t in enumerate(tokens)}
|
| 162 |
+
known_types = {"void", "int", "long", "float", "double", "vec3", "string", "Tool", "Plane", "UV", "AABB", "Config"} | set(re.findall(r"\btype\s+(\w+)\s*=",code))
|
| 163 |
+
type_pattern = "|".join(re.escape(t) for t in sorted(known_types))
|
| 164 |
+
for match in re.finditer(r'^[ \t]*((?:(?:' + type_pattern + r')\b[^\n\r;={}]*?|\([^\n\r;={}]*\)[\[\]& \t]*))[ \t&]+([A-Za-z_]\w*)[ \t]*\(', code, re.M):
|
| 165 |
+
prefix = match[1].strip()
|
| 166 |
+
if not prefix or prefix.split()[0] in ('if', 'while', 'for', 'return', 'switch', 'else'):
|
| 167 |
+
continue
|
| 168 |
+
opening = token_offsets.get(match.end()-1)
|
| 169 |
+
if opening is None:
|
| 170 |
+
continue
|
| 171 |
+
args, end = arguments(tokens, opening)
|
| 172 |
+
headers.append({'name': match[2], 'line': source.count('\n',0,match.start(2))+1,
|
| 173 |
+
'offset': match.start(2), 'signature': re.sub(r'\s+', ' ', source[match.start(1):tokens[end]['end']]).strip(),
|
| 174 |
+
'declaration': tokens[end+1]['text'] == ';' if end+1 < len(tokens) else False})
|
| 175 |
+
wrappers = []
|
| 176 |
+
for call in calls:
|
| 177 |
+
if call['method'] == 'interrupt':
|
| 178 |
+
preceding = [h for h in headers if h['offset'] < call['offset'] and not h['declaration']]
|
| 179 |
+
wrapper = preceding[-1] if preceding else None
|
| 180 |
+
wrappers.append({**call, 'wrapper': wrapper})
|
| 181 |
+
bindings = {}
|
| 182 |
+
for i,t in enumerate(tokens[:-2]):
|
| 183 |
+
if t['kind'] == 'identifier' and tokens[i+1]['text'] == '=':
|
| 184 |
+
j, depth = i+2, 0
|
| 185 |
+
while j < len(tokens):
|
| 186 |
+
value = tokens[j]['text'] if tokens[j]['kind'] == 'symbol' else ''
|
| 187 |
+
if value in ('(', '[', '{'): depth += 1
|
| 188 |
+
elif value in (')', ']', '}'): depth -= 1
|
| 189 |
+
if depth < 0 or (depth == 0 and value in (',', ';')): break
|
| 190 |
+
j += 1
|
| 191 |
+
expr = tokens[i+2:j]
|
| 192 |
+
if expr and all(x['kind'] == 'string' or x['text'] == '+' or x['kind'] == 'identifier' for x in expr):
|
| 193 |
+
bindings.setdefault(t['text'], []).append({'expression': text_of(source,expr), 'line':t['line']})
|
| 194 |
+
return {'includes': includes, 'aliases': aliases, 'constants': constants, 'qualified_calls': calls,
|
| 195 |
+
'interrupt_wrappers': wrappers, 'string_bindings': bindings}
|
| 196 |
+
|
| 197 |
+
|
| 198 |
+
def literal_string(expression, bindings, trail=()):
|
| 199 |
+
"""Resolve only an unambiguous concatenation of literals and local bindings.
|
| 200 |
+
|
| 201 |
+
Scope/flow is not reconstructed: conflicting same-named declarations remain
|
| 202 |
+
unresolved, even when a human could infer the active one.
|
| 203 |
+
"""
|
| 204 |
+
parts = lex(expression)
|
| 205 |
+
if not parts or len(parts) % 2 == 0 or any(t['text'] != '+' for t in parts[1::2]):
|
| 206 |
+
return None
|
| 207 |
+
result = ''
|
| 208 |
+
for token in parts[::2]:
|
| 209 |
+
value = token['text']
|
| 210 |
+
if token['kind'] == 'string':
|
| 211 |
+
if value.startswith('\\"'):
|
| 212 |
+
result += value[3:-2]
|
| 213 |
+
else:
|
| 214 |
+
result += re.sub(r"\\([rnt\\\"'])", lambda m: {'r':'\r','n':'\n','t':'\t'}.get(m[1],m[1]), value[1:-1])
|
| 215 |
+
elif token['kind'] == 'identifier' and value in bindings and value not in trail:
|
| 216 |
+
candidates = [literal_string(x['expression'],bindings,(*trail,value)) for x in bindings[value]]
|
| 217 |
+
if not candidates or any(x is None for x in candidates) or len(set(candidates)) != 1:
|
| 218 |
+
return None
|
| 219 |
+
result += candidates[0]
|
| 220 |
+
else:
|
| 221 |
+
return None
|
| 222 |
+
return result
|
| 223 |
+
|
| 224 |
+
|
| 225 |
+
def category(path):
|
| 226 |
+
p = PurePosixPath(path)
|
| 227 |
+
if p.suffix == '.ixpl':
|
| 228 |
+
if '/plugins/extra stuff/' in path: return 'experimental-plugin'
|
| 229 |
+
if '/plugins/' in path: return 'plugin'
|
| 230 |
+
if '/models/' in path: return 'model-generator'
|
| 231 |
+
if '/include/core/' in path: return 'host-api'
|
| 232 |
+
if '/include/tasks/' in path: return 'task-client'
|
| 233 |
+
return 'ixpl-library'
|
| 234 |
+
if p.suffix == '.exe': return 'executable-unexamined'
|
| 235 |
+
if 'grammar' in p.name: return 'grammar'
|
| 236 |
+
return {'.bat':'batch-script','.cfg':'configuration','.shader':'shader','.png':'image'}.get(p.suffix,'reference-text')
|
| 237 |
+
|
| 238 |
+
|
| 239 |
+
def index_build(root, inventory):
|
| 240 |
+
files = {x['path']:x for x in inventory['files']}
|
| 241 |
+
paths = set(files)
|
| 242 |
+
include_roots = [PurePosixPath('tools') / p.replace('\\','/') for p in (root/'tools/includePaths.txt').read_text().splitlines() if p.strip()]
|
| 243 |
+
# Normalize relative traversal in trusted include search directories only.
|
| 244 |
+
include_roots = [Path(root/p).resolve().relative_to(root.resolve()).as_posix() for p in include_roots]
|
| 245 |
+
records = []
|
| 246 |
+
for path, item in sorted(files.items()):
|
| 247 |
+
raw = (root/path).read_bytes()
|
| 248 |
+
if hashlib.sha256(raw).hexdigest() != item['sha256']:
|
| 249 |
+
raise ValueError(f'Modified/unhydrated source: {root/path}')
|
| 250 |
+
record = {'path':path,'sha256':item['sha256'],'bytes':len(raw),'category':category(path),
|
| 251 |
+
'coverage':'lexically-indexed' if PurePosixPath(path).suffix.lower() in {'.ixpl','.shader','.cfg'} or category(path)=='grammar' else 'text-inventoried' if PurePosixPath(path).suffix.lower() in TEXT_SUFFIXES else 'inventory-only',
|
| 252 |
+
'owner':'Nanobrush reference research',
|
| 253 |
+
'followup':{'host-api':'P4.03','plugin':'P4.08','experimental-plugin':'P4.09','task-client':'P4.05','ixpl-library':'P4.07','model-generator':'P9.06','grammar':'P6.01','executable-unexamined':'P3.06','shader':'P9.01','configuration':'P8.09','image':'P9.05','batch-script':'P4.12'}.get(category(path),'P3.02')}
|
| 254 |
+
if PurePosixPath(path).suffix.lower() in TEXT_SUFFIXES:
|
| 255 |
+
try: text,encoding = raw.decode('utf-8-sig'),'utf-8-sig'
|
| 256 |
+
except UnicodeDecodeError: text,encoding = raw.decode('cp1252'),'cp1252-fallback'
|
| 257 |
+
record.update(encoding=encoding,lines=len(text.splitlines()))
|
| 258 |
+
if path.endswith('.ixpl'):
|
| 259 |
+
record.update(scan_ixpl(text))
|
| 260 |
+
for edge in record['includes']:
|
| 261 |
+
candidates = [PurePosixPath(path).parent/edge['include'],*(PurePosixPath(d)/edge['include'] for d in include_roots)]
|
| 262 |
+
edge['candidates'] = sorted({c.as_posix() for c in candidates if c.as_posix() in paths})
|
| 263 |
+
edge['status'] = 'resolved-candidate' if len(edge['candidates'])==1 else 'ambiguous' if edge['candidates'] else 'missing'
|
| 264 |
+
elif path.endswith('.shader'):
|
| 265 |
+
record['sections'] = [{'name':m[1],'line':text.count('\n',0,m.start())+1} for m in re.finditer(r'\[@([^\]]+)\]',text)]
|
| 266 |
+
record['uniforms'] = [{'type':m[1],'name':m[2],'line':text.count('\n',0,m.start())+1} for m in re.finditer(r'\buniform\s+(\w+)\s+(\w+)\s*;',text)]
|
| 267 |
+
elif path.endswith('.cfg'):
|
| 268 |
+
record['keys'] = [{'type':m[1],'key':m[2],'line':text.count('\n',0,m.start())+1} for m in re.finditer(r'^\s*(bool|int|long|float|double|vec3|string)\s+([\w.]+)\s*=',text,re.M)]
|
| 269 |
+
elif record['category']=='grammar':
|
| 270 |
+
record['rules'] = [{'name':m[1],'line':text.count('\n',0,m.start())+1} for m in re.finditer(r'^\s*(#?\w+)\s*=\s*\{',text,re.M)]
|
| 271 |
+
elif path.endswith('.bat'):
|
| 272 |
+
record['lines_text'] = [{'line':i,'text':line} for i,line in enumerate(text.splitlines(),1) if line.strip()]
|
| 273 |
+
records.append(record)
|
| 274 |
+
core = [r for r in records if r['category']=='host-api']
|
| 275 |
+
values, pending = {},[(r,c) for r in core for c in r.get('constants',[])]
|
| 276 |
+
while pending:
|
| 277 |
+
progress = False
|
| 278 |
+
for r,c in pending[:]:
|
| 279 |
+
try: value = constant_value(c['expression'],values)
|
| 280 |
+
except (ValueError,SyntaxError): continue
|
| 281 |
+
values[c['name']] = value;c['value']=value;pending.remove((r,c));progress=True
|
| 282 |
+
if not progress:break
|
| 283 |
+
for r in records:
|
| 284 |
+
if r['category']!='host-api':continue
|
| 285 |
+
for wrapper in r.get('interrupt_wrappers',[]):
|
| 286 |
+
argument = wrapper['arguments'][0]
|
| 287 |
+
try: wrapper['interrupt_id'] = constant_value(argument,values)
|
| 288 |
+
except (ValueError,SyntaxError): wrapper['interrupt_id']=None
|
| 289 |
+
graph = {r['path']:sorted({p for e in r.get('includes',[]) for p in e['candidates']}) for r in records if r['path'].endswith('.ixpl')}
|
| 290 |
+
for r in records:
|
| 291 |
+
if r['category'] not in ('plugin','experimental-plugin','model-generator'):continue
|
| 292 |
+
seen,stack = set(),list(graph[r['path']])
|
| 293 |
+
while stack:
|
| 294 |
+
path=stack.pop()
|
| 295 |
+
if path in seen:continue
|
| 296 |
+
seen.add(path);stack.extend(graph.get(path,[]))
|
| 297 |
+
r['transitive_includes']=sorted(seen)
|
| 298 |
+
r['core_calls']=sorted({c['method'] for c in r['qualified_calls'] if c['qualifier']=='Core'})
|
| 299 |
+
r['interface_lookups']=[c for c in r['qualified_calls'] if c['method']=='getToolID']
|
| 300 |
+
r['registrations']=[c for c in r['qualified_calls'] if c['method'] in ('initTool','registerPackage','setRuntimeOnAllLoaded','setRuntimeOnFinalization')]
|
| 301 |
+
r['registered_names'] = []
|
| 302 |
+
for call in r['registrations']:
|
| 303 |
+
if call['method'] != 'initTool': continue
|
| 304 |
+
args = call['arguments']
|
| 305 |
+
name = literal_string(args[0],r['string_bindings']) if args else None
|
| 306 |
+
if name is None and len(args)>1: name = literal_string(args[1],r['string_bindings'])
|
| 307 |
+
r['registered_names'].append({'line':call['line'],'name':name,'arguments':args})
|
| 308 |
+
r['resource_calls']=[c for c in r['qualified_calls'] if c['method'] in ('loadConfigFile','saveConfigFile','loadGUITexture','loadTextFile','saveTextFile','callProgram','saveWorldToFile','loadWorldFromFile')]
|
| 309 |
+
for call in r['resource_calls']:
|
| 310 |
+
literal = literal_string(call['arguments'][0],r['string_bindings']) if call['arguments'] else None
|
| 311 |
+
call['literal_path'] = literal
|
| 312 |
+
call['exact_name_candidates'] = sorted(p for p in paths if literal is not None and (p == literal.replace('\\','/') or PurePosixPath(p).name == PurePosixPath(literal.replace('\\','/')).name))
|
| 313 |
+
call['status'] = 'dynamic' if literal is None else 'exact-name-candidate' if call['exact_name_candidates'] else 'not-present-by-exact-name'
|
| 314 |
+
|
| 315 |
+
return {'build':inventory['build'],'archive_sha256':inventory['archive_sha256'],'include_search_roots':include_roots,
|
| 316 |
+
'categories':dict(sorted(Counter(r['category'] for r in records).items())),
|
| 317 |
+
'unresolved_core_constants':[{'path':r['path'],**c} for r,c in pending], 'files':records}
|
| 318 |
+
|
| 319 |
+
|
| 320 |
+
def differences(builds):
|
| 321 |
+
result=[]
|
| 322 |
+
for old,new in zip(builds,builds[1:]):
|
| 323 |
+
a={f['path']:f['sha256'] for f in old['files']};b={f['path']:f['sha256'] for f in new['files']}
|
| 324 |
+
added,removed=sorted(b.keys()-a.keys()),sorted(a.keys()-b.keys())
|
| 325 |
+
result.append({'from':old['build'],'to':new['build'],'added':added,'removed':removed,
|
| 326 |
+
'changed':[p for p in sorted(a.keys()&b.keys()) if a[p]!=b[p]],
|
| 327 |
+
'identical_rename_candidates':[{'from':p,'to':q} for p in removed for q in added if a[p]==b[q]],
|
| 328 |
+
'identical_copy_candidates':[{'from':p,'to':q} for p in sorted(a) for q in added if p not in removed and a[p]==b[q]],
|
| 329 |
+
'modified_same_basename_candidates':[{'from':p,'to':q} for p in removed for q in added if PurePosixPath(p).name==PurePosixPath(q).name and a[p]!=b[q]]})
|
| 330 |
+
return result
|
| 331 |
+
|
| 332 |
+
|
| 333 |
+
def validate_report(builds):
|
| 334 |
+
"""Corpus-level closure checks, separate from the permissive lexical scanner."""
|
| 335 |
+
for build in builds:
|
| 336 |
+
if build['unresolved_core_constants']:
|
| 337 |
+
raise ValueError('Unresolved Core constants: ' + build['build'])
|
| 338 |
+
core = [f for f in build['files'] if f['category'] == 'host-api']
|
| 339 |
+
declared = {c['value'] for f in core for c in f['constants'] if c['name'].startswith('INT_')}
|
| 340 |
+
wrappers = [w for f in core for w in f.get('interrupt_wrappers', [])]
|
| 341 |
+
if {w.get('interrupt_id') for w in wrappers} != declared or declared != set(range(max(declared)+1)):
|
| 342 |
+
raise ValueError('Core endpoint coverage/range differs: ' + build['build'])
|
| 343 |
+
if any(w['wrapper'] is None or w['wrapper']['line'] != w['line'] for w in wrappers):
|
| 344 |
+
raise ValueError('A Core interrupt has no same-line signature: ' + build['build'])
|
| 345 |
+
if any(len(e['candidates']) != 1 for f in build['files'] for e in f.get('includes', [])):
|
| 346 |
+
raise ValueError('Include candidate closure differs: ' + build['build'])
|
| 347 |
+
|
| 348 |
+
|
| 349 |
+
def render_api_index(build):
|
| 350 |
+
lines = ['# Core interrupt index', '',
|
| 351 |
+
'Source-only endpoint enumeration for build `2016-03-10-c`. IDs are evaluated source constants, not a binary dispatch trace. Full signatures, arguments and older builds are in [source-map.json](../assets/analysis/source-map.json). See [HOST_APIS.md](HOST_APIS.md).', '']
|
| 352 |
+
for item in build['files']:
|
| 353 |
+
if item['category'] != 'host-api' or not item.get('interrupt_wrappers'):
|
| 354 |
+
continue
|
| 355 |
+
lines += ['## ' + PurePosixPath(item['path']).name, '',
|
| 356 |
+
'Source: `' + item['path'] + '`; SHA-256 `' + item['sha256'] + '`.', '',
|
| 357 |
+
'| ID | Constant(s) | Wrapper(s), source lines |', '| ---: | --- | --- |']
|
| 358 |
+
groups = defaultdict(list)
|
| 359 |
+
for wrapper in item['interrupt_wrappers']:
|
| 360 |
+
groups[wrapper['interrupt_id']].append(wrapper)
|
| 361 |
+
for value, wrappers in sorted(groups.items()):
|
| 362 |
+
constants = sorted({w['arguments'][0].lstrip('+').strip() for w in wrappers})
|
| 363 |
+
names = ', '.join('`' + w['wrapper']['name'] + '`:' + str(w['line']) for w in wrappers)
|
| 364 |
+
lines.append('| ' + str(value) + ' | ' + ', '.join('`' + c + '`' for c in constants) + ' | ' + names + ' |')
|
| 365 |
+
lines.append('')
|
| 366 |
+
return '\n'.join(lines)
|
| 367 |
+
|
| 368 |
+
|
| 369 |
+
def render_plugin_index(build):
|
| 370 |
+
lines = ['# Plugin tool registration index', '',
|
| 371 |
+
'Baseline `2016-03-10-c`. These are lexical `initTool` call sites, including internal/service tools and experiments. Conservative name resolution does not prove runtime reachability, load order or simultaneous registration. See [PLUGINS.md](PLUGINS.md).', '']
|
| 372 |
+
for item in build['files']:
|
| 373 |
+
if not item.get('registered_names'):
|
| 374 |
+
continue
|
| 375 |
+
lines += ['## ' + PurePosixPath(item['path']).stem, '',
|
| 376 |
+
'Source: `' + item['path'] + '`; SHA-256 `' + item['sha256'] + '`.', '',
|
| 377 |
+
'| Tool name expression resolved to | Line | Press callback expression |', '| --- | ---: | --- |']
|
| 378 |
+
for entry in item['registered_names']:
|
| 379 |
+
args = entry['arguments']
|
| 380 |
+
direct = literal_string(args[0], item['string_bindings']) is not None
|
| 381 |
+
index = 1 if direct else 2
|
| 382 |
+
callback = args[index] if len(args) > index else 'unknown'
|
| 383 |
+
escape = lambda value: value.replace('|', '\\|').replace('\n', ' ')
|
| 384 |
+
lines.append('| `' + escape(entry['name'] or '(unresolved)') + '` | ' + str(entry['line']) + ' | `' + escape(callback) + '` |')
|
| 385 |
+
lines.append('')
|
| 386 |
+
return '\n'.join(lines)
|
| 387 |
+
|
| 388 |
+
|
| 389 |
+
def main():
|
| 390 |
+
parser=argparse.ArgumentParser(description=__doc__);parser.add_argument('--check',action='store_true');args=parser.parse_args()
|
| 391 |
+
builds=[]
|
| 392 |
+
for p in json.loads(references.MANIFEST.read_text())['packages']:
|
| 393 |
+
inventory=references.inspect_archive(references.REFERENCES/'archives'/p['filename'],p)
|
| 394 |
+
root=references.REFERENCES/'extracted'/p['build'];references.check_extracted(root,inventory)
|
| 395 |
+
builds.append(index_build(root,inventory))
|
| 396 |
+
validate_report(builds)
|
| 397 |
+
report={'schema':1,'method':'static lexical source index; no reference execution','generator_sha256':hashlib.sha256(Path(__file__).read_bytes()).hexdigest(),
|
| 398 |
+
'limitations':['Include resolution records candidates, not measured compiler search order.','Qualified calls are lexical references, not proven execution or a typed call graph.','CP1252 is an explicit fallback, not an established encoding contract.','No host implementation, binary serializer, or bytecode layout is inferred from an API declaration.'],
|
| 399 |
+
'builds':builds,'version_differences':differences(builds)}
|
| 400 |
+
documents = {ROOT/'docs/API_INDEX.md':render_api_index(builds[-1]), ROOT/'docs/PLUGIN_INDEX.md':render_plugin_index(builds[-1])}
|
| 401 |
+
if args.check:
|
| 402 |
+
if not OUT.exists() or json.loads(OUT.read_text())!=report:raise ValueError('Static map is absent/stale; regenerate it')
|
| 403 |
+
for path,content in documents.items():
|
| 404 |
+
if not path.exists() or path.read_text()!=content:raise ValueError(f'Stale generated index: {path}')
|
| 405 |
+
else:
|
| 406 |
+
references.write_json(OUT,report)
|
| 407 |
+
for path,content in documents.items():path.write_text(content)
|
| 408 |
+
print(json.dumps({'builds':len(builds),'files':sum(len(b['files']) for b in builds),'latest_categories':builds[-1]['categories'],'report':str(OUT.relative_to(ROOT))},indent=2))
|
| 409 |
+
|
| 410 |
+
|
| 411 |
+
if __name__=='__main__':
|
| 412 |
+
try:main()
|
| 413 |
+
except (OSError,ValueError) as error:print(f'Source map: {error}',file=sys.stderr);sys.exit(1)
|
tests/test_map_references.py
ADDED
|
@@ -0,0 +1,87 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""Static-index correctness tests independent of the original payload corpus."""
|
| 2 |
+
import hashlib
|
| 3 |
+
from pathlib import Path
|
| 4 |
+
import tempfile
|
| 5 |
+
import unittest
|
| 6 |
+
|
| 7 |
+
import map_references as mapper
|
| 8 |
+
|
| 9 |
+
|
| 10 |
+
class LexicalMappingTests(unittest.TestCase):
|
| 11 |
+
def test_comments_and_literals_do_not_become_dependencies(self):
|
| 12 |
+
source = '''// #include "fake1.ixpl"
|
| 13 |
+
/* C::loadConfigFile("bad.cfg"); */
|
| 14 |
+
string x = "C::fake(1)";
|
| 15 |
+
string raw = \\"[\n#include "fake2.ixpl"\nC::fake(2);\n]";
|
| 16 |
+
#include "Core.ixpl"
|
| 17 |
+
namespace C = Core;
|
| 18 |
+
void real() { C::loadConfigFile("real.cfg", cfg); }
|
| 19 |
+
'''
|
| 20 |
+
report = mapper.scan_ixpl(source)
|
| 21 |
+
self.assertEqual([(x['include'],x['line']) for x in report['includes']], [('Core.ixpl',8)])
|
| 22 |
+
self.assertEqual([(c['qualifier'],c['method']) for c in report['qualified_calls']], [('Core','loadConfigFile')])
|
| 23 |
+
|
| 24 |
+
def test_balanced_call_arguments_and_opaque_commas(self):
|
| 25 |
+
source = 'namespace C = Core;\nvoid f() { C::queueTask(id, int[]{1, 2}, nested(3, 4), "x,y"); }'
|
| 26 |
+
call = mapper.scan_ixpl(source)['qualified_calls'][0]
|
| 27 |
+
self.assertEqual(call['arguments'],['id','int[]{1, 2}','nested(3, 4)','"x,y"'])
|
| 28 |
+
|
| 29 |
+
def test_interrupt_overloads_keep_signatures_and_source_lines(self):
|
| 30 |
+
source = ('int INT_A = 7;\nvoid get(int &x);\n'
|
| 31 |
+
'void get(int &x) interrupt(+INT_A, x);\n'
|
| 32 |
+
'int get() {int x; interrupt(+INT_A, x); return x;}\n')
|
| 33 |
+
wrappers = mapper.scan_ixpl(source)['interrupt_wrappers']
|
| 34 |
+
self.assertEqual([w['wrapper']['signature'] for w in wrappers],['void get(int &x)','int get()'])
|
| 35 |
+
self.assertEqual([w['line'] for w in wrappers],[3,4])
|
| 36 |
+
self.assertEqual(mapper.constant_value(wrappers[0]['arguments'][0],{'INT_A':7}),7)
|
| 37 |
+
|
| 38 |
+
def test_historical_struct_return_is_not_attached_to_previous_wrapper(self):
|
| 39 |
+
source = ('type Brush = (int x);\nvoid deselect(int x) interrupt(+1,x);\n'
|
| 40 |
+
'Brush &read() {Brush b; interrupt(+2,b); return b;}\n')
|
| 41 |
+
wrappers=mapper.scan_ixpl(source)['interrupt_wrappers']
|
| 42 |
+
self.assertEqual(wrappers[1]['wrapper']['name'],'read')
|
| 43 |
+
self.assertEqual(wrappers[1]['wrapper']['line'],3)
|
| 44 |
+
self.assertEqual(wrappers[1]['line'],3)
|
| 45 |
+
|
| 46 |
+
def test_numeric_resolution_is_not_code_execution(self):
|
| 47 |
+
self.assertEqual(mapper.constant_value('_INT_BEGIN + 5',{'_INT_BEGIN':249}),254)
|
| 48 |
+
for value in ['__import__("os").system("bad")','X + 1','2 * 3']:
|
| 49 |
+
with self.subTest(value=value), self.assertRaises(ValueError):
|
| 50 |
+
mapper.constant_value(value,{})
|
| 51 |
+
|
| 52 |
+
def test_literal_names_resolve_only_unambiguous_bindings(self):
|
| 53 |
+
report = mapper.scan_ixpl('string prefix = "camera.";\nstring name = prefix+"toggle";')
|
| 54 |
+
self.assertEqual(mapper.literal_string('name',report['string_bindings']),'camera.toggle')
|
| 55 |
+
for value in ['missing','"bad"+','call()']:
|
| 56 |
+
self.assertIsNone(mapper.literal_string(value,report['string_bindings']))
|
| 57 |
+
self.assertIsNone(mapper.literal_string('prefix',{'prefix':[{'expression':'"a"'},{'expression':'"b"'}]}))
|
| 58 |
+
self.assertIsNone(mapper.literal_string('cycle',{'cycle':[{'expression':'cycle'}]}))
|
| 59 |
+
|
| 60 |
+
def test_large_multiline_literal_is_opaque(self):
|
| 61 |
+
source = 'string data = \\"[' + (' ' * 1000 + '\n') * 80 + ']";\nvoid f() { Core::undo(); }'
|
| 62 |
+
self.assertEqual(mapper.scan_ixpl(source)['qualified_calls'][0]['method'],'undo')
|
| 63 |
+
for source in ['/* unterminated','string s = "bad','string s = \\"[bad']:
|
| 64 |
+
with self.assertRaises(ValueError):mapper.lex(source)
|
| 65 |
+
|
| 66 |
+
def test_build_graph_reports_missing_and_ambiguous_candidates(self):
|
| 67 |
+
with tempfile.TemporaryDirectory() as temp:
|
| 68 |
+
root = Path(temp).resolve()
|
| 69 |
+
content = {'tools/includePaths.txt':b'..\\inc1\n..\\inc2\n',
|
| 70 |
+
'inc1/Core.ixpl':b'namespace Core {}', 'inc2/Core.ixpl':b'namespace Core {}',
|
| 71 |
+
'data/sources/plugins/tool.ixpl':b'#include "Core.ixpl"\n#include "Missing.ixpl"\n'}
|
| 72 |
+
inventory = {'build':'synthetic','archive_sha256':'a'*64,'files':[]}
|
| 73 |
+
for name,raw in content.items():
|
| 74 |
+
path=root/name;path.parent.mkdir(parents=True,exist_ok=True);path.write_bytes(raw)
|
| 75 |
+
inventory['files'].append({'path':name,'sha256':hashlib.sha256(raw).hexdigest()})
|
| 76 |
+
build = mapper.index_build(root,inventory)
|
| 77 |
+
plugin = next(f for f in build['files'] if f['category']=='plugin')
|
| 78 |
+
self.assertEqual([e['status'] for e in plugin['includes']],['ambiguous','missing'])
|
| 79 |
+
(root/'inc1/Core.ixpl').write_bytes(b'changed')
|
| 80 |
+
with self.assertRaises(ValueError):mapper.index_build(root,inventory)
|
| 81 |
+
|
| 82 |
+
def test_diffs_distinguish_renames_copies_and_changes(self):
|
| 83 |
+
old={'build':'a','files':[{'path':'old.txt','sha256':'1'},{'path':'retained.txt','sha256':'2'}]}
|
| 84 |
+
new={'build':'b','files':[{'path':'new.txt','sha256':'1'},{'path':'retained.txt','sha256':'2'}, {'path':'copy.txt','sha256':'2'}]}
|
| 85 |
+
diff=mapper.differences([old,new])[0]
|
| 86 |
+
self.assertEqual(diff['identical_rename_candidates'],[{'from':'old.txt','to':'new.txt'}])
|
| 87 |
+
self.assertEqual(diff['identical_copy_candidates'],[{'from':'retained.txt','to':'copy.txt'}])
|