# DVX Loader Bootstrap loader for the DVX desktop environment. Builds as `dvx.exe` -- the only native executable in the system. Everything else is a dynamically loaded DXE3 module. ## What It Does 1. Changes working directory to the directory containing `dvx.exe` 2. Truncates `dvx.log` and initializes logging 3. Calls `platformInit()` to suppress Ctrl+C and install signal handlers 4. Calls `platformRegisterDxeExports()` to register platform and C runtime symbols (libc, libm, libgcc) for DXE module resolution 5. Scans and loads all modules in two phases (see below) 6. Finds `shellMain()` via `dlsym` across loaded modules 7. Calls `shellMain()` -- the shell takes over from here 8. On return, closes all module handles in reverse load order ## Two-Phase Module Loading ### Phase 1: Libraries (libs/*.lib) Recursively scans the `LIBS/` directory for `.lib` files. Each module may have a `.dep` file (same base name, `.dep` extension) listing base names of modules that must load first. The loader resolves the dependency graph and loads in topological order. Load order (via dep files): ``` libtasks.lib (no deps) libdvx.lib (deps: libtasks) texthelp.lib (deps: libtasks, libdvx) listhelp.lib (deps: libtasks, libdvx) dvxshell.lib (deps: libtasks, libdvx, texthelp, listhelp) taskmgr.lib (deps: dvxshell, libtasks, libdvx, texthelp, listhelp) ``` ### Phase 2: Widgets (widgets/*.wgt) Recursively scans the `WIDGETS/` directory for `.wgt` files. Widget modules may also have `.dep` files (e.g., `textinpt.dep` lists `texthelp`). Loaded in topological order, same as libs. After loading each module, the loader checks for a `wgtRegister` export. If present, it is called immediately so the widget registers its class(es) and API with the core. ## Dependency File Format Plain text, one dependency base name per line. Empty lines and lines starting with `#` are ignored. Names are case-insensitive. Example (`combobox.dep`): ``` texthelp listhelp ``` ## Hosted Components ### dvxLog() The global logging function is defined in `loaderMain.c` and exported to all DXE modules. It appends a line to `dvx.log`, opening and closing the file per write so it is never held open. ```c void dvxLog(const char *fmt, ...); ``` ### stb_ds The `STB_DS_IMPLEMENTATION` is compiled into the loader with `STBDS_REALLOC` and `STBDS_FREE` overridden to use `dvxRealloc` and `dvxFree`. This means all `arrput`/`hmput`/`arrfree` calls in DXE code route through the per-app memory tracker, so stb_ds memory is attributed correctly in the Task Manager's memory column. stb_ds functions are exported to all DXE modules via the platform export table. ### Platform Layer `dvxPlatformDos.c` is compiled into the loader (not into libdvx.lib). All platform functions are exported to DXE modules. This includes: * Video: VESA VBE init, LFB mapping, mode enumeration * Input: INT 33h mouse, INT 16h keyboard, CuteMouse wheel API * Spans: `rep stosl`/`rep movsd` asm inner loops (8/16/32 bpp) * DXE: symbol registration, symbol overrides * Crash: signal handler installation, register dump logging * System: memory info, directory creation, path utilities ### Per-App Memory Tracking The DXE export table maps standard C allocation symbols to tracked wrappers: | C Symbol | Mapped To | Effect | |----------|-----------|--------| | `malloc` | `dvxMalloc` | Allocations attributed to `currentAppId` | | `calloc` | `dvxCalloc` | Same | | `realloc` | `dvxRealloc` | Transfers attribution on resize | | `free` | `dvxFree` | Decrements app's tracked usage | | `strdup` | `dvxStrdup` | Tracks the duplicated string | This is transparent to DXE code -- apps call `malloc` normally and the tracked wrapper runs instead. The Task Manager reads per-app usage via `dvxMemGetAppUsage()`. When an app is reaped, `dvxMemResetApp()` zeroes its counter. ## Files | File | Description | |------|-------------| | `loaderMain.c` | Entry point, module scanner, dependency resolver, logger | | `Makefile` | Builds `bin/dvx.exe` | ## Build ``` make # builds bin/dvx.exe make clean # removes objects and binary ``` The loader links `loaderMain.c` + `dvxPlatformDos.c` into a native DJGPP executable. The CWSDPMI stub is prepended via exe2coff + CWSDSTUB.EXE for standalone execution.