226 lines
10 KiB
Markdown
226 lines
10 KiB
Markdown
# DVX -- DOS Visual eXecutive
|
|
|
|
A windowed GUI compositor and widget toolkit targeting DJGPP/DPMI on
|
|
486+ hardware. VESA VBE 2.0+ LFB only. Motif-inspired visual style
|
|
with 2px bevels, fixed bitmap fonts, and dirty-rect compositing.
|
|
|
|
The system runs on 86Box (primary target) and real DOS hardware.
|
|
|
|
|
|
## Architecture
|
|
|
|
DVX is built as a set of DXE3 dynamic modules loaded by a bootstrap
|
|
executable. The loader resolves dependencies and loads modules in
|
|
topological order, then hands control to the shell.
|
|
|
|
```
|
|
dvx.exe (loader)
|
|
|
|
|
+-- libs/libtasks.lib cooperative task switcher
|
|
+-- libs/libdvx.lib core GUI (draw, comp, wm, app, widget infra)
|
|
+-- libs/texthelp.lib shared text editing helpers
|
|
+-- libs/listhelp.lib shared list/dropdown helpers
|
|
+-- libs/dvxshell.lib shell (app lifecycle, desktop)
|
|
+-- libs/taskmgr.lib task manager (Ctrl+Esc, separate DXE)
|
|
|
|
|
+-- libs/basrt.lib BASIC runtime (VM + values)
|
|
+-- libs/serial.lib serial communications (rs232 + packet + seclink)
|
|
|
|
|
+-- widgets/*.wgt 26 widget type plugins
|
|
|
|
|
+-- apps/*/*.app DXE applications
|
|
```
|
|
|
|
|
|
## Directory Structure
|
|
|
|
| Directory | Output | Description |
|
|
|--------------|-------------------------|--------------------------------------------|
|
|
| `loader/` | `bin/dvx.exe` | Bootstrap loader, platform layer, stb_ds |
|
|
| `core/` | `bin/libs/libdvx.lib` | Core GUI library (5 layers + widget infra) |
|
|
| `tasks/` | `bin/libs/libtasks.lib` | Cooperative task switching |
|
|
| `texthelp/` | `bin/libs/texthelp.lib` | Shared text editing helpers |
|
|
| `listhelp/` | `bin/libs/listhelp.lib` | Shared list/dropdown helpers |
|
|
| `shell/` | `bin/libs/dvxshell.lib` | DVX Shell (app lifecycle, desktop) |
|
|
| `taskmgr/` | `bin/libs/taskmgr.lib` | Task Manager (separate DXE, Ctrl+Esc) |
|
|
| `widgets/` | `bin/widgets/*.wgt` | 26 individual widget DXE modules |
|
|
| `apps/` | `bin/apps/*/*.app` | Application DXE modules |
|
|
| `tools/` | `bin/dvxres`, `bin/mkicon`, `bin/mktbicon` | Resource and icon tools (host native) |
|
|
| `config/` | `bin/config/`, `bin/libs/`, `bin/widgets/` | INI config, themes, wallpapers, dep files |
|
|
| `rs232/` | `lib/librs232.a` | ISR-driven UART serial driver |
|
|
| `packet/` | `lib/libpacket.a` | HDLC framing, CRC-16, Go-Back-N ARQ |
|
|
| `security/` | `lib/libsecurity.a` | DH key exchange, XTEA-CTR cipher, RNG |
|
|
| `seclink/` | `lib/libseclink.a` | Secure serial link (channels, encryption) |
|
|
| `proxy/` | `bin/secproxy` | Linux proxy: 86Box <-> telnet BBS |
|
|
| `termdemo/` | `bin/termdemo.exe` | Standalone encrypted terminal demo |
|
|
|
|
|
|
## Build
|
|
|
|
Requires the DJGPP cross-compiler at `~/djgpp/djgpp`.
|
|
|
|
```
|
|
make # build everything
|
|
make clean # remove all build artifacts
|
|
./mkcd.sh # build + create ISO for 86Box
|
|
```
|
|
|
|
The top-level Makefile builds in dependency order:
|
|
|
|
```
|
|
core -> tasks -> loader -> texthelp -> listhelp -> widgets -> shell -> taskmgr -> apps
|
|
tools (host native, parallel)
|
|
```
|
|
|
|
Build output goes to `bin/` (executables, DXE modules, config) and
|
|
`obj/` (intermediate object files).
|
|
|
|
|
|
## Runtime Directory Layout (bin/)
|
|
|
|
```
|
|
bin/
|
|
dvx.exe bootstrap loader (entry point)
|
|
libs/
|
|
libtasks.lib task switching library
|
|
libdvx.lib core GUI library
|
|
texthelp.lib text editing helpers
|
|
listhelp.lib list/dropdown helpers
|
|
dvxshell.lib DVX shell
|
|
taskmgr.lib task manager (Ctrl+Esc)
|
|
basrt.lib BASIC runtime (VM + values)
|
|
serial.lib serial communications stack
|
|
*.dep dependency files for load ordering
|
|
widgets/
|
|
box.wgt VBox/HBox/Frame containers
|
|
button.wgt push button
|
|
... (26 widget modules total)
|
|
*.dep dependency files
|
|
apps/
|
|
progman/progman.app Program Manager (desktop)
|
|
notepad/notepad.app text editor
|
|
clock/clock.app clock display
|
|
dvxdemo/dvxdemo.app widget showcase
|
|
cpanel/cpanel.app control panel
|
|
imgview/imgview.app image viewer
|
|
dvxbasic/dvxbasic.app DVX BASIC IDE + compiler
|
|
config/
|
|
dvx.ini system configuration
|
|
themes/ color theme files (.thm)
|
|
wpaper/ wallpaper images
|
|
```
|
|
|
|
|
|
## Core Architecture (5 Layers)
|
|
|
|
1. **dvxVideo** -- VESA VBE init, LFB mapping, backbuffer, pixel format, color packing
|
|
2. **dvxDraw** -- Rectangle fills, bevels, text rendering, cursor/icon drawing
|
|
3. **dvxComp** -- Dirty rectangle tracking, merge, compositor, LFB flush
|
|
4. **dvxWm** -- Window stack, chrome, drag/resize, menus, scrollbars, hit testing
|
|
5. **dvxApp** -- Event loop, input polling, public API, color schemes, wallpaper
|
|
|
|
|
|
## Widget System
|
|
|
|
Widgets are isolated DXE modules. Core knows nothing about individual
|
|
widget types -- no compile-time enum, no union, no per-widget structs in
|
|
dvxWidget.h.
|
|
|
|
* **Dynamic type IDs**: `wgtRegisterClass()` assigns IDs at load time
|
|
* **void *data**: Each widget allocates its own private data struct
|
|
* **ABI-stable dispatch**: `WidgetClassT.handlers[]` is an array of function
|
|
pointers indexed by `WGT_METHOD_*` constants (0-20, room for 32). Core
|
|
dispatches via `w->wclass->handlers[WGT_METHOD_PAINT]` etc., so adding
|
|
new methods does not break existing widget DXE binaries
|
|
* **Generic drag**: `WGT_METHOD_ON_DRAG_UPDATE` and `WGT_METHOD_ON_DRAG_END`
|
|
provide widget-level drag support without per-widget hacks in core
|
|
* **Per-widget API registry**: `wgtRegisterApi("name", &api)` replaces the monolithic API
|
|
* **Per-widget headers**: `widgets/widgetButton.h` etc. provide typed macros
|
|
* **Shared helpers**: texthelp.lib (text editing) and listhelp.lib (dropdown/list)
|
|
* **All limits dynamic**: widget child arrays, app slots, and desktop callbacks
|
|
are stb_ds dynamic arrays with no fixed maximums
|
|
|
|
|
|
## DXE Module System
|
|
|
|
All modules are DXE3 dynamic libraries loaded by dvx.exe at startup.
|
|
The loader recursively scans `libs/` for `.lib` files and `widgets/` for `.wgt`
|
|
files, reads `.dep` files for dependencies, and loads in topological
|
|
order. Widget modules that export `wgtRegister()` have it called after
|
|
loading.
|
|
|
|
Each `.dep` file lists base names of modules that must load first, one
|
|
per line. Comments start with `#`.
|
|
|
|
|
|
## App Types
|
|
|
|
**Callback-only** (`hasMainLoop = false`): `appMain` creates windows,
|
|
registers callbacks, and returns. The app lives through event callbacks
|
|
in the shell's main loop. No dedicated task or stack needed.
|
|
|
|
**Main-loop** (`hasMainLoop = true`): A cooperative task is created for
|
|
the app. `appMain` runs its own loop calling `tsYield()` to share CPU.
|
|
Used for apps that need continuous processing (clocks, terminal
|
|
emulators, games).
|
|
|
|
|
|
## Crash Recovery
|
|
|
|
The shell installs signal handlers for SIGSEGV, SIGFPE, and SIGILL
|
|
before loading any apps, so even crashes during app initialization are
|
|
caught. If an app crashes, the handler `longjmp`s back to the shell's
|
|
main loop, the crashed app is force-killed, and the shell continues
|
|
running. Diagnostic information (registers, faulting EIP) is logged to
|
|
`dvx.log`.
|
|
|
|
|
|
## Bundled Applications
|
|
|
|
| App | File | Type | Description |
|
|
|-----------------|----------------|-----------|------------------------------------------------------------|
|
|
| Program Manager | `progman.app` | Callback | App launcher grid, system info dialog |
|
|
| Notepad | `notepad.app` | Callback | Text editor with File/Edit menus, open/save, clipboard |
|
|
| Clock | `clock.app` | Main-loop | Digital clock display; multi-instance capable |
|
|
| DVX Demo | `dvxdemo.app` | Callback | Widget system showcase demonstrating 31 widget types |
|
|
| Control Panel | `cpanel.app` | Callback | Themes, wallpaper, video mode, mouse configuration |
|
|
| Image Viewer | `imgview.app` | Callback | Displays BMP, PNG, JPEG, GIF images with aspect-ratio zoom |
|
|
| DVX BASIC | `dvxbasic.app` | Callback | Visual Basic 3 clone: form designer, compiler, VM |
|
|
|
|
|
|
## Serial / Networking Stack
|
|
|
|
A layered encrypted serial communications stack for connecting DVX to
|
|
remote systems (BBS, etc.) through 86Box's emulated UART:
|
|
|
|
| Layer | Library | Description |
|
|
|----------|------------------|---------------------------------------------------|
|
|
| rs232 | `librs232.a` | ISR-driven UART driver, ring buffers, flow control |
|
|
| packet | `libpacket.a` | HDLC framing, CRC-16, Go-Back-N ARQ |
|
|
| security | `libsecurity.a` | 1024-bit DH, XTEA-CTR cipher, DRBG RNG |
|
|
| seclink | `libseclink.a` | Channel multiplexing, per-packet encryption |
|
|
| proxy | `secproxy` | Linux bridge: 86Box serial <-> telnet BBS |
|
|
|
|
|
|
## Third-Party Dependencies
|
|
|
|
All third-party code is vendored as single-header libraries:
|
|
|
|
| Library | Location | Purpose |
|
|
|-------------------|--------------------|---------------------------------|
|
|
| stb_image.h | `core/thirdparty/` | Image loading (BMP, PNG, JPEG, GIF) |
|
|
| stb_image_write.h | `core/thirdparty/` | PNG export for screenshots |
|
|
| stb_ds.h | `core/thirdparty/` | Dynamic arrays and hash maps |
|
|
|
|
stb_ds implementation is compiled into dvx.exe (the loader) with
|
|
`STBDS_REALLOC`/`STBDS_FREE` overridden to use `dvxRealloc`/`dvxFree`,
|
|
so all `arrput`/`arrfree` calls in DXE code are tracked per-app. The
|
|
functions are exported via `dlregsym` to all DXE modules.
|
|
|
|
|
|
## Target Hardware
|
|
|
|
* CPU: 486 baseline, Pentium-optimized paths where significant
|
|
* Video: VESA VBE 2.0+ with LFB (no bank switching)
|
|
* Platform: 86Box emulator (trusted reference), real DOS hardware
|
|
* Resolutions: 640x480, 800x600, 1024x768 at 8/15/16/32 bpp
|