| .. | ||
| dvxshell.dhs | ||
| Makefile | ||
| README.md | ||
| shellApp.c | ||
| shellApp.h | ||
| shellInf.h | ||
| shellInfo.c | ||
| shellMain.c | ||
DVX Shell (dvxshell.lib)
The DVX Shell is a DXE3 module loaded by the DVX loader at startup. It initializes the GUI subsystem, loads DXE3 application modules on demand, runs the cooperative main loop, and provides crash recovery so a faulting app does not bring down the entire system.
Entry Point
The loader finds and calls shellMain() after all libs and widgets
are loaded. shellMain():
- Loads preferences from
CONFIG/DVX.INI - Initializes the GUI via
dvxInit()with configured video mode - Applies saved mouse, color, and wallpaper settings from INI
- Shows a splash screen ("DVX - DOS Visual eXecutive / Loading...")
- Initializes the cooperative task system (
tsInit()) - Sets shell task (task 0) to
TS_PRIORITY_HIGH - Gathers system information via the platform layer
- Initializes the app slot table
- Points the memory tracker at
currentAppIdfor per-app attribution - Registers idle callback, Ctrl+Esc handler, and title change handler
- Installs the crash handler (before loading apps, so init crashes are caught)
- Loads the desktop app (default:
apps/progman/progman.app) - Dismisses the splash screen
- Enters the main loop
Main Loop
Each iteration of the main loop does four things:
dvxUpdate()-- process input events, dispatch callbacks, composite dirty rects, flush to LFBtsYield()-- give CPU time to app tasks (if any are active)shellReapApps()-- clean up any apps that terminated this frameshellDesktopUpdate()-- notify desktop app if apps were reaped
An idle callback (idleYield) is also registered so that dvxUpdate()
yields to app tasks during quiet frames.
App Lifecycle
DXE App Contract
Every DXE app exports two symbols:
-
appDescriptor(AppDescriptorT) -- metadata:name-- display name (max 64 chars)hasMainLoop-- true for main-loop apps, false for callback-onlymultiInstance-- true to allow multiple instances via temp copystackSize--SHELL_STACK_DEFAULT(32KB) or explicit byte countpriority--TS_PRIORITY_NORMALor custom
-
appMain(int appMain(DxeAppContextT *)) -- entry point
Optional export: appShutdown (void appShutdown(void)) -- called
during graceful shutdown.
Callback-Only Apps (hasMainLoop = false)
appMain() is called directly in the shell's task 0. It creates
windows, registers callbacks, and returns immediately. The app lives
entirely through GUI callbacks. The shell reaps callback-only apps
automatically when their last window closes -- shellReapApps() checks
each frame for running callback apps with zero remaining windows.
Main-Loop Apps (hasMainLoop = true)
A dedicated cooperative task is created. appMain() runs in that task
and can do its own polling/processing loop, calling tsYield() to
share CPU. Lifecycle ends when appMain() returns or the task is
killed.
App States
Free -> Loaded -> Running -> Terminating -> Free
| State | Description |
|---|---|
AppStateFreeE |
Slot available for reuse |
AppStateLoadedE |
DXE loaded, not yet started (transient) |
AppStateRunningE |
Entry point called, active |
AppStateTerminatingE |
Shutdown in progress, awaiting reap |
App Slots
App slots are managed as a stb_ds dynamic array (no fixed max). Each
slot tracks: app ID, name, path, DXE handle, state, task ID, entry/
shutdown function pointers, and a pointer to the DxeAppContextT
passed to the app.
DxeAppContextT is heap-allocated (via calloc) so its address is
stable across sApps array reallocs -- apps save this pointer in their
static globals and it must not move. The shell frees it during reap.
The DxeAppContextT gives each app:
shellCtx-- pointer to the shell'sAppContextTappId-- this app's unique IDappDir-- directory containing the.appfile (for resources)configDir-- writable config directory (CONFIG/<apppath>/)
App ID Tracking
ctx->currentAppId on AppContextT tracks which app is currently
executing. The shell sets this before calling app code.
dvxCreateWindow() stamps win->appId directly so the shell can
associate windows with apps for cleanup.
For main-loop apps, appTaskWrapper receives the app ID (as an int
cast to void *), not a direct pointer to ShellAppT. This is because
the sApps dynamic array may reallocate between tsCreate and the
first time the task runs, which would invalidate a direct pointer.
The shell calls dvxSetBusy() before dlopen to show the hourglass
cursor during app loading, and clears it after appMain returns (for
callback apps) or after task creation (for main-loop apps).
Crash Recovery
The platform layer installs signal handlers for SIGSEGV, SIGFPE, and
SIGILL via platformInstallCrashHandler(). If a crash occurs:
- Platform handler logs signal name and register dump (DJGPP)
- Handler
longjmps to thesetjmppoint inshellMain() tsRecoverToMain()fixes the scheduler's bookkeeping- Shell logs app-specific info (name, path, task ID)
- Crashed app is force-killed (
shellForceKillApp()) - Error dialog is shown to the user
- Desktop is notified to refresh
- Main loop continues normally
This gives Windows 3.1-style fault tolerance -- one bad app does not take down the whole system.
Task Manager Integration
The Task Manager is a separate DXE (taskmgr.lib in taskmgr/), not
built into the shell. It registers itself at load time via a DXE
constructor that sets the shellCtrlEscFn function pointer. The shell
calls this pointer on Ctrl+Esc. If taskmgr.lib is not loaded,
shellCtrlEscFn is NULL and Ctrl+Esc does nothing.
See taskmgr/README.md for full Task Manager documentation.
Desktop Update Notifications
Apps (especially the desktop app) register callbacks via
shellRegisterDesktopUpdate() to be notified when app state changes
(load, reap, crash, title change). Multiple callbacks are supported.
Files
| File | Description |
|---|---|
shellMain.c |
Entry point, main loop, crash recovery, splash screen, idle callback |
shellApp.h |
App lifecycle types: AppDescriptorT, DxeAppContextT, ShellAppT, AppStateE; shellCtrlEscFn extern |
shellApp.c |
App loading, reaping, task creation, DXE management, per-app memory tracking |
shellInfo.h |
System information wrapper |
shellInfo.c |
Gathers and caches hardware info via platform layer |
Makefile |
Builds bin/libs/dvxshell.lib + config/themes/wallpapers |
Build
make # builds dvxshell.lib + dvxshell.dep + config files
make clean # removes objects, library, and config output
Depends on: libtasks.lib, libdvx.lib, texthelp.lib, listhelp.lib
(via dvxshell.dep).