1045 lines
40 KiB
HTML
1045 lines
40 KiB
HTML
<!DOCTYPE html>
|
|
<html lang="en">
|
|
<head>
|
|
<meta charset="utf-8">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
<title>DVX Architecture Overview</title>
|
|
<style>
|
|
body {
|
|
font-family: "Segoe UI", Tahoma, Geneva, Verdana, sans-serif;
|
|
line-height: 1.6;
|
|
color: #1a1a1a;
|
|
max-width: 960px;
|
|
margin: 0 auto;
|
|
padding: 2em 1.5em;
|
|
background: #fdfdfd;
|
|
}
|
|
h1 {
|
|
font-size: 2em;
|
|
border-bottom: 3px solid #333;
|
|
padding-bottom: 0.3em;
|
|
margin-bottom: 0.5em;
|
|
}
|
|
h2 {
|
|
font-size: 1.5em;
|
|
border-bottom: 1px solid #999;
|
|
padding-bottom: 0.2em;
|
|
margin-top: 2em;
|
|
}
|
|
h3 {
|
|
font-size: 1.2em;
|
|
margin-top: 1.5em;
|
|
}
|
|
pre {
|
|
background: #f4f4f4;
|
|
border: 1px solid #ddd;
|
|
border-radius: 4px;
|
|
padding: 1em;
|
|
overflow-x: auto;
|
|
font-family: "Consolas", "Courier New", monospace;
|
|
font-size: 0.9em;
|
|
line-height: 1.4;
|
|
}
|
|
code {
|
|
font-family: "Consolas", "Courier New", monospace;
|
|
font-size: 0.9em;
|
|
background: #f0f0f0;
|
|
padding: 0.1em 0.3em;
|
|
border-radius: 2px;
|
|
}
|
|
pre code {
|
|
background: none;
|
|
padding: 0;
|
|
}
|
|
table {
|
|
border-collapse: collapse;
|
|
width: 100%;
|
|
margin: 1em 0;
|
|
}
|
|
th, td {
|
|
border: 1px solid #ccc;
|
|
padding: 0.5em 0.8em;
|
|
text-align: left;
|
|
}
|
|
th {
|
|
background: #e8e8e8;
|
|
font-weight: bold;
|
|
}
|
|
tr:nth-child(even) {
|
|
background: #f9f9f9;
|
|
}
|
|
.note {
|
|
background: #fff8e1;
|
|
border-left: 4px solid #ffc107;
|
|
padding: 0.8em 1em;
|
|
margin: 1em 0;
|
|
}
|
|
.diagram {
|
|
background: #f9f9f9;
|
|
border: 2px solid #bbb;
|
|
border-radius: 4px;
|
|
padding: 1em 1.5em;
|
|
overflow-x: auto;
|
|
}
|
|
ul {
|
|
margin: 0.5em 0;
|
|
}
|
|
li {
|
|
margin-bottom: 0.3em;
|
|
}
|
|
dt {
|
|
font-weight: bold;
|
|
margin-top: 0.8em;
|
|
}
|
|
dd {
|
|
margin-left: 1.5em;
|
|
margin-bottom: 0.5em;
|
|
}
|
|
.toc {
|
|
background: #f4f4f4;
|
|
border: 1px solid #ddd;
|
|
border-radius: 4px;
|
|
padding: 1em 1.5em;
|
|
margin: 1.5em 0;
|
|
}
|
|
.toc ul {
|
|
list-style: none;
|
|
padding-left: 0;
|
|
}
|
|
.toc li {
|
|
margin: 0.3em 0;
|
|
}
|
|
.toc a {
|
|
text-decoration: none;
|
|
color: #0066cc;
|
|
}
|
|
.toc a:hover {
|
|
text-decoration: underline;
|
|
}
|
|
a {
|
|
color: #0066cc;
|
|
}
|
|
.subtitle {
|
|
color: #555;
|
|
font-size: 1.1em;
|
|
margin-top: -0.5em;
|
|
margin-bottom: 1.5em;
|
|
}
|
|
</style>
|
|
</head>
|
|
<body>
|
|
|
|
<h1>DVX Architecture Overview</h1>
|
|
<p class="subtitle">DOS Visual eXecutive -- A Windowing GUI for DJGPP/DPMI</p>
|
|
|
|
<div class="toc">
|
|
<strong>Contents</strong>
|
|
<ul>
|
|
<li><a href="#overview">1. System Overview</a></li>
|
|
<li><a href="#layers">2. Five-Layer Architecture</a></li>
|
|
<li><a href="#pipeline">3. Display Pipeline</a></li>
|
|
<li><a href="#windows">4. Window System</a></li>
|
|
<li><a href="#widgets">5. Widget System</a></li>
|
|
<li><a href="#dxe">6. DXE Module System</a></li>
|
|
<li><a href="#events">7. Event Model</a></li>
|
|
<li><a href="#fonts">8. Font System</a></li>
|
|
<li><a href="#colors">9. Color System</a></li>
|
|
<li><a href="#platform">10. Platform Layer</a></li>
|
|
<li><a href="#build">11. Build System</a></li>
|
|
</ul>
|
|
</div>
|
|
|
|
<!-- =================================================================== -->
|
|
<h2 id="overview">1. System Overview</h2>
|
|
|
|
<p>
|
|
DVX (DOS Visual eXecutive) is a complete windowing GUI compositor targeting
|
|
<strong>DJGPP/DPMI</strong> on DOS. It provides overlapping windows with
|
|
Motif-style chrome, a retained-mode widget toolkit, cooperative multitasking
|
|
of DXE-loaded applications, and a dirty-rectangle compositor optimized for
|
|
486/Pentium hardware.
|
|
</p>
|
|
|
|
<p>Key design constraints:</p>
|
|
<ul>
|
|
<li><strong>VESA VBE 2.0+ LFB only</strong> -- no bank switching. If the
|
|
hardware cannot provide a linear framebuffer, initialization fails.</li>
|
|
<li><strong>486 baseline</strong> -- all hot paths are written to be fast on
|
|
a 486, with Pentium-specific paths where the gain is significant.</li>
|
|
<li><strong>Single-tasking cooperative model</strong> -- applications yield
|
|
the CPU via <code>tsYield()</code>; there is no preemptive scheduler.</li>
|
|
<li><strong>86Box</strong> is the trusted reference platform for testing.
|
|
DOSBox-X is not used; any bugs observed are treated as DVX bugs.</li>
|
|
<li><strong>No external font or cursor files</strong> -- all bitmaps are
|
|
compiled in as static const data.</li>
|
|
</ul>
|
|
|
|
<p>The runtime environment consists of a bootstrap loader
|
|
(<code>dvx.exe</code>) that loads core DXE libraries, widget plugins, and
|
|
the shell, which in turn loads and manages DXE application modules.</p>
|
|
|
|
<!-- =================================================================== -->
|
|
<h2 id="layers">2. Five-Layer Architecture</h2>
|
|
|
|
<p>DVX is organized into five layers, each implemented as a single
|
|
<code>.h</code>/<code>.c</code> pair. Every header includes
|
|
<code>dvxTypes.h</code> (the shared type definitions) to avoid circular
|
|
dependencies. The layers are strictly stacked: each layer depends only on the
|
|
layers below it.</p>
|
|
|
|
<div class="diagram">
|
|
<pre><code>
|
|
Applications (DXE .app modules)
|
|
==================================================
|
|
| |
|
|
| +------------------------------------------+ |
|
|
| | Layer 5: dvxApp (Application API) | | dvxApp.h / dvxApp.c
|
|
| | Event loop, window creation, public API | |
|
|
| +------------------------------------------+ |
|
|
| | Layer 4: dvxWm (Window Manager) | | dvxWm.h / dvxWm.c
|
|
| | Window stack, chrome, drag, resize | |
|
|
| +------------------------------------------+ |
|
|
| | Layer 3: dvxComp (Compositor) | | dvxComp.h / dvxComp.c
|
|
| | Dirty rect tracking, merge, LFB flush | |
|
|
| +------------------------------------------+ |
|
|
| | Layer 2: dvxDraw (Drawing Primitives) | | dvxDraw.h / dvxDraw.c
|
|
| | Rects, bevels, text, blits, cursors | |
|
|
| +------------------------------------------+ |
|
|
| | Layer 1: dvxVideo (Video Backend) | | dvxVideo.h / dvxVideo.c
|
|
| | VESA VBE, LFB mapping, pixel format | |
|
|
| +------------------------------------------+ |
|
|
| |
|
|
| +------------------------------------------+ |
|
|
| | Platform Layer (dvxPlatform.h) | | dvxPlatformDos.c
|
|
| | OS-specific: video, input, asm spans | |
|
|
| +------------------------------------------+ |
|
|
| |
|
|
| +------------------------------------------+ |
|
|
| | Shared Types (dvxTypes.h) | |
|
|
| | DisplayT, WindowT, RectT, ColorSchemeT | |
|
|
| +------------------------------------------+ |
|
|
==================================================
|
|
</code></pre>
|
|
</div>
|
|
|
|
<table>
|
|
<tr><th>Layer</th><th>Header</th><th>Responsibility</th></tr>
|
|
<tr>
|
|
<td>1 - Video</td>
|
|
<td><code>dvxVideo.h</code></td>
|
|
<td>VESA VBE mode negotiation, LFB mapping via DPMI, backbuffer
|
|
allocation, <code>packColor()</code> (RGB to native pixel format),
|
|
display-wide clip rectangle.</td>
|
|
</tr>
|
|
<tr>
|
|
<td>2 - Draw</td>
|
|
<td><code>dvxDraw.h</code></td>
|
|
<td>All 2D drawing operations: <code>rectFill</code>, <code>rectCopy</code>,
|
|
<code>drawBevel</code>, <code>drawText</code>/<code>drawTextN</code>,
|
|
<code>drawMaskedBitmap</code> (cursor), <code>drawTermRow</code>
|
|
(batch terminal row rendering). Stateless beyond the clip rect on
|
|
DisplayT. Dispatches hot inner loops through <code>BlitOpsT</code>
|
|
function pointers.</td>
|
|
</tr>
|
|
<tr>
|
|
<td>3 - Compositor</td>
|
|
<td><code>dvxComp.h</code></td>
|
|
<td>Dirty rectangle tracking (<code>dirtyListAdd</code>), pairwise merge
|
|
of overlapping rects (<code>dirtyListMerge</code>), and the
|
|
<code>flushRect</code> function that copies dirty regions from the
|
|
system RAM backbuffer to the LFB.</td>
|
|
</tr>
|
|
<tr>
|
|
<td>4 - Window Manager</td>
|
|
<td><code>dvxWm.h</code></td>
|
|
<td>Window lifecycle, Z-order stack, chrome drawing (title bars, bevels,
|
|
close/minimize/maximize gadgets), hit testing, drag/resize, menu bars,
|
|
scrollbars, system menu, keyboard move/resize mode, minimized icon
|
|
bar.</td>
|
|
</tr>
|
|
<tr>
|
|
<td>5 - Application</td>
|
|
<td><code>dvxApp.h</code></td>
|
|
<td>Public API aggregating all layers into <code>AppContextT</code>.
|
|
Provides <code>dvxInit</code>/<code>dvxShutdown</code>,
|
|
<code>dvxRun</code>/<code>dvxUpdate</code>, window creation
|
|
helpers, image loading, clipboard, accelerator tables, theme
|
|
management, wallpaper, video mode switching, screenshot capture.</td>
|
|
</tr>
|
|
</table>
|
|
|
|
<!-- =================================================================== -->
|
|
<h2 id="pipeline">3. Display Pipeline</h2>
|
|
|
|
<p>The double-buffer strategy is the single most important performance
|
|
decision in DVX. All drawing goes to a <strong>system RAM backbuffer</strong>
|
|
(<code>DisplayT.backBuf</code>); only dirty rectangles are flushed to the
|
|
<strong>linear framebuffer</strong> (<code>DisplayT.lfb</code>) in video
|
|
memory.</p>
|
|
|
|
<p>This matters because writes to video memory over the PCI bus are
|
|
10-50x slower than writes to main RAM on 486/Pentium hardware for
|
|
random-access patterns.</p>
|
|
|
|
<h3>Per-Frame Compositing Pipeline</h3>
|
|
|
|
<pre><code> 1. Input poll (mouse, keyboard)
|
|
|
|
|
2. Event dispatch (focus window callbacks)
|
|
|
|
|
3. Layers call dirtyListAdd() for changed regions
|
|
|
|
|
4. dirtyListMerge() consolidates overlapping rects
|
|
|
|
|
5. For each merged dirty rect:
|
|
a. Clip and redraw desktop background (or wallpaper)
|
|
b. For each window (back-to-front, painter's algorithm):
|
|
- wmDrawChrome() -- frame, title bar, gadgets, menu bar
|
|
- wmDrawContent() -- blit per-window content buffer
|
|
- wmDrawScrollbars()
|
|
c. Draw minimized window icons
|
|
d. Draw popup menus / tooltips (overlay pass)
|
|
e. Draw software mouse cursor
|
|
|
|
|
6. flushRect() -- copy each dirty rect from backBuf to LFB
|
|
|
|
|
7. Yield (platformYield)
|
|
</code></pre>
|
|
|
|
<h3>Key Data Structures</h3>
|
|
|
|
<dl>
|
|
<dt><code>DisplayT</code></dt>
|
|
<dd>Central display context: width, height, pitch, pixel format, LFB pointer,
|
|
backbuffer pointer, palette, clip rectangle. Passed by pointer through
|
|
every layer -- no globals.</dd>
|
|
|
|
<dt><code>BlitOpsT</code></dt>
|
|
<dd>Vtable of span fill/copy function pointers resolved at init time for the
|
|
active pixel depth. On DOS these dispatch to hand-written <code>rep stosl</code>
|
|
/ <code>rep movsd</code> asm inner loops.</dd>
|
|
|
|
<dt><code>DirtyListT</code></dt>
|
|
<dd>Fixed-capacity dynamic array of <code>RectT</code>. Linear scanning for
|
|
merge candidates is cache-friendly at typical sizes (under 128 rects).
|
|
If the list fills up, the compositor merges aggressively or falls back to
|
|
full-screen repaint.</dd>
|
|
</dl>
|
|
|
|
<h3>Why This Works on a 486</h3>
|
|
<ul>
|
|
<li>A full 640x480x32bpp frame is 1.2 MB -- far too much to flush every
|
|
frame over a slow PCI bus.</li>
|
|
<li>A typical dirty region during normal interaction (typing, menu open)
|
|
is a few KB.</li>
|
|
<li>Merging overlapping dirty rects into larger rects reduces per-rect
|
|
overhead and improves bus utilization.</li>
|
|
<li>Per-window content buffers persist across frames, so windows don't
|
|
repaint on expose -- only when their own content changes.</li>
|
|
</ul>
|
|
|
|
<!-- =================================================================== -->
|
|
<h2 id="windows">4. Window System</h2>
|
|
|
|
<h3>WindowT Structure</h3>
|
|
|
|
<p>Each <code>WindowT</code> is the central object of the window manager. Key
|
|
fields:</p>
|
|
|
|
<table>
|
|
<tr><th>Field Group</th><th>Purpose</th></tr>
|
|
<tr><td>Geometry (<code>x, y, w, h</code>)</td>
|
|
<td>Outer frame rectangle (including chrome).</td></tr>
|
|
<tr><td>Content area (<code>contentX/Y/W/H</code>)</td>
|
|
<td>Computed from frame minus chrome. Where application content lives.</td></tr>
|
|
<tr><td>Content buffer (<code>contentBuf, contentPitch</code>)</td>
|
|
<td>Per-window backbuffer in native pixel format. Persists across frames.</td></tr>
|
|
<tr><td>Chrome state (<code>menuBar, vScroll, hScroll</code>)</td>
|
|
<td>Optional menu bar and scrollbars. Affect content area computation.</td></tr>
|
|
<tr><td>Widget tree (<code>widgetRoot</code>)</td>
|
|
<td>Root of the retained-mode widget tree (NULL if using raw callbacks).</td></tr>
|
|
<tr><td>Callbacks</td>
|
|
<td><code>onPaint</code>, <code>onKey</code>, <code>onKeyUp</code>,
|
|
<code>onMouse</code>,
|
|
<code>onResize</code>, <code>onClose</code>, <code>onMenu</code>,
|
|
<code>onScroll</code>, <code>onFocus</code>, <code>onBlur</code>,
|
|
<code>onCursorQuery</code>.</td></tr>
|
|
</table>
|
|
|
|
<h3>Window Stack (Z-Order)</h3>
|
|
|
|
<p><code>WindowStackT</code> is an array of <code>WindowT*</code> ordered
|
|
front-to-back: index <code>count-1</code> is the topmost window. This allows:</p>
|
|
<ul>
|
|
<li>Back-to-front iteration for painting (painter's algorithm).</li>
|
|
<li>Front-to-back iteration for hit testing (first hit wins).</li>
|
|
<li>Reordering by pointer swap (no copying of large WindowT structs).</li>
|
|
</ul>
|
|
|
|
<p>Only one drag/resize/scroll operation can be active system-wide at a time
|
|
(single mouse), so that state lives on the stack, not on individual windows.</p>
|
|
|
|
<h3>Chrome Layout</h3>
|
|
|
|
<pre><code> +-------------------------------------------+
|
|
| 4px outer border (raised bevel) |
|
|
| +-------------------------------------+ |
|
|
| | [X] Title Bar Text [_] [^] [X] | | 20px title height
|
|
| +-------------------------------------+ |
|
|
| | 2px inner border | |
|
|
| +-------------------------------------+ |
|
|
| | Menu Bar (optional, 20px) | |
|
|
| +-------------------------------------+ |
|
|
| | | |
|
|
| | Content Area | |
|
|
| | | |
|
|
| | | S | | S = vertical scrollbar
|
|
| | | B | | (16px wide)
|
|
| +-------------------------------------+ |
|
|
| | Horizontal Scrollbar (optional) | | 16px tall
|
|
| +-------------------------------------+ |
|
|
| 4px outer border |
|
|
+-------------------------------------------+
|
|
</code></pre>
|
|
|
|
<p>Chrome constants are compile-time defines:</p>
|
|
<pre><code> CHROME_BORDER_WIDTH = 4px
|
|
CHROME_TITLE_HEIGHT = 20px
|
|
CHROME_INNER_BORDER = 2px
|
|
CHROME_MENU_HEIGHT = 20px
|
|
SCROLLBAR_WIDTH = 16px
|
|
CHROME_CLOSE_BTN_SIZE = 16px
|
|
</code></pre>
|
|
|
|
<h3>Hit Test Regions</h3>
|
|
<p>
|
|
<code>wmHitTest()</code> iterates the stack front-to-back and returns a
|
|
hit-part identifier: <code>HIT_CONTENT</code>, <code>HIT_TITLE</code>,
|
|
<code>HIT_CLOSE</code>, <code>HIT_RESIZE</code>, <code>HIT_MENU</code>,
|
|
<code>HIT_VSCROLL</code>, <code>HIT_HSCROLL</code>,
|
|
<code>HIT_MINIMIZE</code>, <code>HIT_MAXIMIZE</code>.
|
|
Resize edge detection returns a bitmask of <code>RESIZE_LEFT</code>,
|
|
<code>RESIZE_RIGHT</code>, <code>RESIZE_TOP</code>,
|
|
<code>RESIZE_BOTTOM</code> (corners combine two edges).
|
|
</p>
|
|
|
|
<h3>Menu System</h3>
|
|
<p>
|
|
Menus use fixed-size arrays with inline <code>char</code> buffers (no heap
|
|
strings). Up to 8 menus per bar, items dynamically allocated. Supports
|
|
cascading submenus via <code>MenuItemT.subMenu</code> pointer. Item types:
|
|
normal, checkbox, radio. Separators are non-interactive items. The popup
|
|
state (<code>PopupStateT</code>) tracks a stack of parent frames for
|
|
cascading submenu nesting.
|
|
</p>
|
|
|
|
<h3>Minimized Windows</h3>
|
|
<p>
|
|
Minimized windows display as 64x64 icons at the bottom of the screen with
|
|
beveled borders, similar to a classic desktop icon bar. Icons show a
|
|
scaled-down preview of the window's content buffer, refreshed one per frame
|
|
in a round-robin fashion to amortize the scaling cost.
|
|
</p>
|
|
|
|
<!-- =================================================================== -->
|
|
<h2 id="widgets">5. Widget System</h2>
|
|
|
|
<p>The widget system (<code>dvxWidget.h</code>) is a retained-mode toolkit
|
|
layered on top of the window manager. Widgets form a tree rooted at a
|
|
per-window VBox container.</p>
|
|
|
|
<h3>WidgetT Base Structure</h3>
|
|
<p>Every widget shares the same <code>WidgetT</code> struct. The
|
|
<code>type</code> field is a runtime-assigned integer ID.
|
|
The <code>wclass</code> pointer references the widget's
|
|
<code>WidgetClassT</code> vtable. Widget-specific private data is stored in
|
|
<code>w->data</code> (opaque <code>void*</code>).</p>
|
|
|
|
<p>Tree linkage: <code>parent</code>, <code>firstChild</code>,
|
|
<code>lastChild</code>, <code>nextSibling</code>. No
|
|
<code>prevSibling</code> -- this halves pointer overhead and removal is
|
|
still O(n) for typical tree depths of 5-10.</p>
|
|
|
|
<h3>Layout Engine</h3>
|
|
|
|
<p>Two-pass flexbox-like algorithm:</p>
|
|
<ol>
|
|
<li><strong>Bottom-up (calcMinSize)</strong> -- compute minimum sizes for
|
|
every widget, starting from leaves.</li>
|
|
<li><strong>Top-down (layout)</strong> -- allocate space within available
|
|
bounds, distributing extra space according to <code>weight</code>
|
|
values (0 = fixed, 100 = normal stretch).</li>
|
|
</ol>
|
|
|
|
<p>Size hints use a tagged encoding: the top 2 bits of an <code>int32_t</code>
|
|
select the unit (pixels, character widths, or percentage of parent), the low
|
|
30 bits hold the value. Macros: <code>wgtPixels(v)</code>,
|
|
<code>wgtChars(v)</code>, <code>wgtPercent(v)</code>.</p>
|
|
|
|
<h3>Widget Class Dispatch (WidgetClassT)</h3>
|
|
|
|
<p>Each widget type provides a <code>WidgetClassT</code> with a
|
|
<code>handlers[]</code> array indexed by stable method IDs. Method IDs are
|
|
never reordered or reused -- new methods append at the end. This provides
|
|
ABI-stable dispatch so that widget DXEs compiled against an older DVX
|
|
version continue to work.</p>
|
|
|
|
<p>Methods include: <code>PAINT</code>, <code>PAINT_OVERLAY</code>,
|
|
<code>CALC_MIN_SIZE</code>, <code>LAYOUT</code>, <code>ON_MOUSE</code>,
|
|
<code>ON_KEY</code>, <code>ON_ACCEL_ACTIVATE</code>, <code>DESTROY</code>,
|
|
<code>GET_TEXT</code>, <code>SET_TEXT</code>, <code>POLL</code>, and more
|
|
(21 defined, room for 32).</p>
|
|
|
|
<p>Class flags encode static properties:</p>
|
|
<table>
|
|
<tr><th>Flag</th><th>Meaning</th></tr>
|
|
<tr><td><code>WCLASS_FOCUSABLE</code></td><td>Can receive keyboard focus (Tab navigation)</td></tr>
|
|
<tr><td><code>WCLASS_HORIZ_CONTAINER</code></td><td>Lays out children horizontally (HBox)</td></tr>
|
|
<tr><td><code>WCLASS_PAINTS_CHILDREN</code></td><td>Widget handles child rendering itself</td></tr>
|
|
<tr><td><code>WCLASS_SCROLLABLE</code></td><td>Accepts mouse wheel events</td></tr>
|
|
<tr><td><code>WCLASS_SCROLL_CONTAINER</code></td><td>ScrollPane -- scrolling viewport</td></tr>
|
|
<tr><td><code>WCLASS_NEEDS_POLL</code></td><td>Needs periodic polling (e.g. AnsiTerm comms)</td></tr>
|
|
<tr><td><code>WCLASS_SWALLOWS_TAB</code></td><td>Tab key goes to widget, not focus navigation</td></tr>
|
|
<tr><td><code>WCLASS_PRESS_RELEASE</code></td><td>Click = press + release (buttons)</td></tr>
|
|
</table>
|
|
|
|
<h3>Available Widget Types</h3>
|
|
|
|
<p>Each widget is a separate <code>.wgt</code> DXE module. 29 widget types
|
|
are included:</p>
|
|
|
|
<table>
|
|
<tr><th>Widget</th><th>Description</th></tr>
|
|
<tr><td>Box (VBox/HBox)</td><td>Vertical and horizontal layout containers</td></tr>
|
|
<tr><td>Button</td><td>Clickable push button with label</td></tr>
|
|
<tr><td>Canvas</td><td>Raw drawing surface for custom painting</td></tr>
|
|
<tr><td>Checkbox</td><td>Boolean toggle with checkmark</td></tr>
|
|
<tr><td>ComboBox</td><td>Text input with dropdown list</td></tr>
|
|
<tr><td>DataCtrl</td><td>Data-bound control for database operations</td></tr>
|
|
<tr><td>DbGrid</td><td>Database grid (tabular data display)</td></tr>
|
|
<tr><td>Dropdown</td><td>Dropdown selection list</td></tr>
|
|
<tr><td>Image</td><td>Static image display</td></tr>
|
|
<tr><td>ImageButton</td><td>Button with bitmap icon</td></tr>
|
|
<tr><td>Label</td><td>Static text label</td></tr>
|
|
<tr><td>ListBox</td><td>Scrollable selection list</td></tr>
|
|
<tr><td>ListView</td><td>Multi-column list with headers and sorting</td></tr>
|
|
<tr><td>ProgressBar</td><td>Determinate progress indicator</td></tr>
|
|
<tr><td>Radio</td><td>Radio button (mutual exclusion group)</td></tr>
|
|
<tr><td>ScrollPane</td><td>Scrollable viewport container</td></tr>
|
|
<tr><td>Separator</td><td>Visual divider line</td></tr>
|
|
<tr><td>Slider</td><td>Value selection via draggable thumb</td></tr>
|
|
<tr><td>Spacer</td><td>Empty space for layout</td></tr>
|
|
<tr><td>Spinner</td><td>Numeric input with up/down arrows</td></tr>
|
|
<tr><td>Splitter</td><td>Resizable split pane</td></tr>
|
|
<tr><td>StatusBar</td><td>Window status bar with sections</td></tr>
|
|
<tr><td>TabControl</td><td>Tabbed page container</td></tr>
|
|
<tr><td>Terminal (AnsiTerm)</td><td>ANSI terminal emulator widget</td></tr>
|
|
<tr><td>TextInput</td><td>Single-line text entry field</td></tr>
|
|
<tr><td>Timer</td><td>Periodic timer events</td></tr>
|
|
<tr><td>Toolbar</td><td>Toolbar with icon buttons</td></tr>
|
|
<tr><td>TreeView</td><td>Hierarchical tree display</td></tr>
|
|
<tr><td>WrapBox</td><td>Flow layout (wrapping horizontal container)</td></tr>
|
|
</table>
|
|
|
|
<h3>Widget API Registry</h3>
|
|
|
|
<p>Each widget DXE registers a small API struct under a name during
|
|
<code>wgtRegister()</code>. Callers retrieve it via
|
|
<code>wgtGetApi("button")</code> and cast to the widget-specific API type.
|
|
Per-widget headers provide typed accessors so callers avoid manual casts.
|
|
Adding a new widget requires zero changes to the core.</p>
|
|
|
|
<h3>Widget Interface Descriptors (WgtIfaceT)</h3>
|
|
|
|
<p>Each widget can register an interface descriptor that describes its
|
|
BASIC-facing properties, methods, and events. These descriptors are used
|
|
by the form runtime and IDE for generic dispatch and property panel
|
|
enumeration. Properties have typed getters/setters
|
|
(<code>WGT_IFACE_STRING</code>, <code>WGT_IFACE_INT</code>,
|
|
<code>WGT_IFACE_BOOL</code>, <code>WGT_IFACE_ENUM</code>).</p>
|
|
|
|
<!-- =================================================================== -->
|
|
<h2 id="dxe">6. DXE Module System</h2>
|
|
|
|
<p>DVX uses DJGPP's <strong>DXE3</strong> (Dynamic eXtension) format for
|
|
all loadable modules. DXE3 supports <code>RTLD_GLOBAL</code> symbol
|
|
sharing -- symbols exported by one module are visible to all subsequently
|
|
loaded modules. This is critical: widget DXEs call core API functions
|
|
(e.g. <code>rectFill</code>, <code>wgtInvalidate</code>) that are exported
|
|
by the core library DXE.</p>
|
|
|
|
<h3>Module Types</h3>
|
|
|
|
<table>
|
|
<tr><th>Extension</th><th>Directory</th><th>Purpose</th><th>Examples</th></tr>
|
|
<tr>
|
|
<td><code>.lib</code></td>
|
|
<td><code>LIBS/</code></td>
|
|
<td>Core libraries loaded first. Provide infrastructure APIs.</td>
|
|
<td><code>libtasks.lib</code> (task switcher),
|
|
<code>libdvx.lib</code> (GUI core),
|
|
<code>dvxshell.lib</code> (shell)</td>
|
|
</tr>
|
|
<tr>
|
|
<td><code>.wgt</code></td>
|
|
<td><code>WIDGETS/</code></td>
|
|
<td>Widget type plugins. Each exports a <code>wgtRegister()</code>
|
|
function called at load time.</td>
|
|
<td><code>button.wgt</code>, <code>listview.wgt</code>,
|
|
<code>terminal.wgt</code></td>
|
|
</tr>
|
|
<tr>
|
|
<td><code>.app</code></td>
|
|
<td><code>APPS/*/</code></td>
|
|
<td>Application modules. Each exports <code>appDescriptor</code>
|
|
and <code>appMain()</code>. Loaded on demand by the shell.</td>
|
|
<td><code>progman.app</code>, <code>notepad.app</code>,
|
|
<code>cpanel.app</code></td>
|
|
</tr>
|
|
</table>
|
|
|
|
<h3>Boot Sequence</h3>
|
|
|
|
<pre><code> dvx.exe (loader)
|
|
|
|
|
+-- Enter VGA mode 13h, display splash screen with progress bar
|
|
|
|
|
+-- Scan LIBS/ for *.lib, WIDGETS/ for *.wgt
|
|
|
|
|
+-- Read .dep files for each module (dependency base names)
|
|
|
|
|
+-- Topological sort: load modules in dependency order
|
|
| - dlopen() with RTLD_GLOBAL
|
|
| - Each .wgt that exports wgtRegister() has it called
|
|
|
|
|
+-- Find and call shellMain() (exported by dvxshell.lib)
|
|
|
|
|
+-- dvxInit() -- video mode, input, font, colors, cursors
|
|
|
|
|
+-- Load desktop app (progman.app)
|
|
|
|
|
+-- Main loop:
|
|
dvxUpdate() -> tsYield() -> shellReapApps()
|
|
</code></pre>
|
|
|
|
<h3>Application Lifecycle</h3>
|
|
|
|
<p>Two kinds of DXE apps:</p>
|
|
|
|
<dl>
|
|
<dt>Callback-only (<code>hasMainLoop = false</code>)</dt>
|
|
<dd><code>appMain()</code> creates windows, registers callbacks, and returns.
|
|
The app lives through GUI callbacks driven by the shell's main loop.
|
|
Lifecycle ends when the last window is closed. No extra task stack
|
|
needed -- simpler and cheaper.</dd>
|
|
|
|
<dt>Main-loop (<code>hasMainLoop = true</code>)</dt>
|
|
<dd>A dedicated cooperative task is created. <code>appMain()</code> runs in
|
|
that task with its own loop, calling <code>tsYield()</code> to share CPU.
|
|
Needed for apps with continuous work (terminal emulators, games).
|
|
Lifecycle ends when <code>appMain()</code> returns.</dd>
|
|
</dl>
|
|
|
|
<h3>Crash Recovery</h3>
|
|
<p>
|
|
The platform layer installs signal handlers for <code>SIGSEGV</code>,
|
|
<code>SIGFPE</code>, <code>SIGILL</code>. On crash, the handler logs
|
|
platform-specific diagnostics (register dump on DJGPP), then
|
|
<code>longjmp</code>s back to the shell's main loop. The crashed app is
|
|
killed; other apps and the shell survive. This provides Windows 3.1-style
|
|
fault tolerance.
|
|
</p>
|
|
|
|
<h3>Per-App Memory Tracking</h3>
|
|
<p>
|
|
All allocations route through <code>dvxMalloc</code>/<code>dvxFree</code>
|
|
wrappers that prepend a 16-byte header recording the owning app ID and
|
|
allocation size. The Task Manager displays per-app memory usage, and leaks
|
|
are detected at app termination.
|
|
</p>
|
|
|
|
<!-- =================================================================== -->
|
|
<h2 id="events">7. Event Model</h2>
|
|
|
|
<p>DVX uses a <strong>cooperative polling model</strong>. The main loop
|
|
(<code>dvxRun</code> / <code>dvxUpdate</code>) runs this cycle each frame:</p>
|
|
|
|
<ol>
|
|
<li><strong>Poll mouse</strong> -- <code>platformMousePoll()</code> returns
|
|
position and button bitmask. Compare with previous frame for
|
|
press/release edge detection.</li>
|
|
<li><strong>Poll keyboard</strong> -- <code>platformKeyboardRead()</code>
|
|
returns ASCII + scancode. Non-blocking; returns false if buffer is
|
|
empty.</li>
|
|
<li><strong>Dispatch to focused window</strong> -- the event loop fires
|
|
window callbacks (<code>onKey</code>, <code>onMouse</code>, etc.)
|
|
on the focused window. If the window has a widget tree, the widget
|
|
system's installed handlers dispatch to individual widgets.</li>
|
|
<li><strong>Compositor pass</strong> -- merge dirty rects, composite,
|
|
flush to LFB.</li>
|
|
<li><strong>Yield</strong> -- <code>platformYield()</code> or idle
|
|
callback.</li>
|
|
</ol>
|
|
|
|
<h3>Event Dispatch Chain</h3>
|
|
<pre><code> Mouse/Keyboard Input
|
|
|
|
|
Global handlers (Ctrl+Esc, modal filter)
|
|
|
|
|
Accelerator table check (focused window)
|
|
|
|
|
Window callback (onMouse / onKey)
|
|
|
|
|
[If widget tree installed:]
|
|
|
|
|
widgetOnMouse / widgetOnKey
|
|
|
|
|
Widget hit test (widgetHitTest)
|
|
|
|
|
wclsOnMouse / wclsOnKey (vtable dispatch)
|
|
|
|
|
Universal callbacks (onClick, onChange, etc.)
|
|
</code></pre>
|
|
|
|
<h3>Accelerator Tables</h3>
|
|
<p>
|
|
Per-window accelerator tables map key + modifier combinations to command IDs.
|
|
The runtime normalizes key/modifier at registration time (uppercase key,
|
|
strip shift from modifiers) so matching at dispatch time is two integer
|
|
comparisons per entry. Matched accelerators fire the window's
|
|
<code>onMenu</code> callback with the command ID, unifying the menu and
|
|
hotkey code paths.
|
|
</p>
|
|
|
|
<h3>Mouse Cursor</h3>
|
|
<p>
|
|
Software-rendered cursor using the classic AND/XOR mask approach. Seven
|
|
cursor shapes are compiled in: arrow, horizontal resize, vertical resize,
|
|
NW-SE diagonal resize, NE-SW diagonal resize, busy (hourglass), and
|
|
crosshair. The cursor is painted into the backbuffer on top of the
|
|
composited frame and the affected region is flushed to the LFB each frame.
|
|
</p>
|
|
|
|
<h3>Double-Click Detection</h3>
|
|
<p>
|
|
Timestamp-based: two clicks on the same target (title bar, minimized icon,
|
|
close gadget) within the configurable double-click interval trigger the
|
|
double-click action. Separate tracking for each target type.
|
|
</p>
|
|
|
|
<!-- =================================================================== -->
|
|
<h2 id="fonts">8. Font System</h2>
|
|
|
|
<p>DVX uses <strong>fixed-width 8-pixel-wide bitmap fonts only</strong>.
|
|
One size is provided: 8x16, matching the standard VGA ROM font
|
|
and CP437 encoding (256 glyphs).</p>
|
|
|
|
<h3>BitmapFontT</h3>
|
|
<pre><code> typedef struct {
|
|
int32_t charWidth; // fixed width per glyph (always 8)
|
|
int32_t charHeight; // 16
|
|
int32_t firstChar; // typically 0
|
|
int32_t numChars; // typically 256
|
|
const uint8_t *glyphData; // packed 1bpp, charHeight bytes per glyph
|
|
} BitmapFontT;
|
|
</code></pre>
|
|
|
|
<p>Design rationale:</p>
|
|
<ul>
|
|
<li>Character positions are pure multiplication (<code>x = col * 8</code>).</li>
|
|
<li>Glyph lookup is a single array index.</li>
|
|
<li>Each scanline of a glyph is exactly one byte (1bpp at 8 pixels wide).</li>
|
|
<li>No glyph-width tables, kerning, or per-character positioning needed.</li>
|
|
<li>8-pixel width aligns with byte boundaries -- no bit shifting in
|
|
per-scanline rendering.</li>
|
|
</ul>
|
|
|
|
<h3>Text Rendering Functions</h3>
|
|
<dl>
|
|
<dt><code>drawChar()</code></dt>
|
|
<dd>Renders a single character. Supports opaque (background fill) and
|
|
transparent modes.</dd>
|
|
|
|
<dt><code>drawTextN()</code></dt>
|
|
<dd>Optimized batch rendering for a known character count. Clips once for
|
|
the entire run, fills background in a single <code>rectFill</code>,
|
|
then overlays glyph foreground pixels. Significantly faster than
|
|
per-character rendering for long runs.</dd>
|
|
|
|
<dt><code>drawTermRow()</code></dt>
|
|
<dd>Renders an 80-column terminal row in a single pass, with per-cell
|
|
foreground/background from a 16-color palette, blink attribute support,
|
|
and cursor rendering. Exists because per-character terminal rendering
|
|
is unacceptably slow on target hardware.</dd>
|
|
|
|
<dt><code>drawTextAccel()</code></dt>
|
|
<dd>Renders text with <code>&</code> accelerator markers. The character
|
|
after <code>&</code> is underlined to indicate the keyboard
|
|
shortcut.</dd>
|
|
</dl>
|
|
|
|
<h3>Performance Optimization</h3>
|
|
<p>
|
|
<code>AppContextT</code> stores a fixed-point 16.16 reciprocal of
|
|
<code>font.charHeight</code> (<code>charHeightRecip</code>) so that dividing
|
|
by charHeight (for pixel-to-row conversion in terminal/text widgets) becomes
|
|
a multiply+shift instead of an integer divide, which costs 40+ cycles on a
|
|
486.
|
|
</p>
|
|
|
|
<!-- =================================================================== -->
|
|
<h2 id="colors">9. Color System</h2>
|
|
|
|
<h3>Pixel Format</h3>
|
|
<p>
|
|
<code>PixelFormatT</code> describes the active VESA mode's pixel encoding.
|
|
Populated once from the VBE mode info block. Stores shift, mask, and bit
|
|
count for each channel so <code>packColor()</code> can convert RGB to native
|
|
format with shift-and-mask arithmetic -- no per-pixel computation.
|
|
</p>
|
|
|
|
<p>Supported depths:</p>
|
|
<table>
|
|
<tr><th>Depth</th><th>Bytes/Pixel</th><th>Notes</th></tr>
|
|
<tr><td>8 bpp</td><td>1</td><td>Palette mode. Nearest-index via 6x6x6 color cube + grey ramp.</td></tr>
|
|
<tr><td>15 bpp</td><td>2</td><td>5-5-5 RGB (1 bit unused).</td></tr>
|
|
<tr><td>16 bpp</td><td>2</td><td>5-6-5 RGB.</td></tr>
|
|
<tr><td>32 bpp</td><td>4</td><td>8-8-8 RGB (8 bits unused).</td></tr>
|
|
</table>
|
|
|
|
<h3>ColorSchemeT -- Theming</h3>
|
|
<p>
|
|
All 20 UI colors are <strong>pre-packed into display pixel format at init
|
|
time</strong>. Every color is a <code>uint32_t</code> that can be written
|
|
directly to the framebuffer with zero per-pixel conversion. The scheme must
|
|
be regenerated on video mode change, but mode changes require re-init
|
|
anyway.
|
|
</p>
|
|
|
|
<p>Color roles mirror classic Motif/Windows 3.x conventions:</p>
|
|
<ul>
|
|
<li><code>desktop</code> -- desktop background</li>
|
|
<li><code>windowFace</code>, <code>windowHighlight</code>,
|
|
<code>windowShadow</code> -- window chrome bevel triplet</li>
|
|
<li><code>activeTitleBg/Fg</code>, <code>inactiveTitleBg/Fg</code> --
|
|
focused vs. unfocused title bar</li>
|
|
<li><code>contentBg/Fg</code> -- window content area</li>
|
|
<li><code>menuBg/Fg</code>, <code>menuHighlightBg/Fg</code> -- menus</li>
|
|
<li><code>buttonFace</code> -- button background</li>
|
|
<li><code>scrollbarBg/Fg/Trough</code> -- scrollbar components</li>
|
|
<li><code>cursorFg/Bg</code> -- mouse cursor colors</li>
|
|
</ul>
|
|
|
|
<p>Source RGB values are kept in <code>AppContextT.colorRgb[]</code> for
|
|
theme save/load. Themes are stored as INI files with a
|
|
<code>[colors]</code> section. The API provides
|
|
<code>dvxLoadTheme()</code>, <code>dvxSaveTheme()</code>,
|
|
<code>dvxSetColor()</code>, and <code>dvxResetColorScheme()</code>.</p>
|
|
|
|
<h3>Bevel Styles</h3>
|
|
<p>
|
|
Bevels are the defining visual element of the Motif aesthetic. Convenience
|
|
macros create bevel style descriptors by swapping highlight and shadow
|
|
colors:
|
|
</p>
|
|
<pre><code> BEVEL_RAISED(colorScheme, borderWidth) -- raised 3D look
|
|
BEVEL_SUNKEN(colorScheme, face, borderWidth) -- sunken/inset look
|
|
BEVEL_TROUGH(colorScheme) -- 1px scrollbar trough
|
|
BEVEL_SB_BUTTON(colorScheme) -- scrollbar button
|
|
</code></pre>
|
|
|
|
<!-- =================================================================== -->
|
|
<h2 id="platform">10. Platform Layer</h2>
|
|
|
|
<p>All OS-specific and CPU-specific code is isolated behind
|
|
<code>dvxPlatform.h</code>. To port DVX, implement a new
|
|
<code>dvxPlatformXxx.c</code> against this header.</p>
|
|
|
|
<h3>Implementations</h3>
|
|
|
|
<table>
|
|
<tr><th>File</th><th>Target</th><th>Details</th></tr>
|
|
<tr>
|
|
<td><code>dvxPlatformDos.c</code></td>
|
|
<td>DJGPP / DPMI</td>
|
|
<td>Real VESA VBE, INT 33h mouse, INT 16h keyboard,
|
|
<code>rep movsd</code>/<code>rep stosl</code> asm spans,
|
|
DPMI physical memory mapping for LFB, INT 9 hook for key-up,
|
|
CuteMouse Wheel API.</td>
|
|
</tr>
|
|
</table>
|
|
|
|
<h3>Abstraction Areas</h3>
|
|
|
|
<dl>
|
|
<dt>Video</dt>
|
|
<dd><code>platformVideoInit()</code> -- mode probe and framebuffer setup.<br>
|
|
<code>platformVideoShutdown()</code> -- restore previous mode.<br>
|
|
<code>platformVideoEnumModes()</code> -- enumerate available modes.</dd>
|
|
|
|
<dt>Framebuffer Flush</dt>
|
|
<dd><code>platformFlushRect()</code> -- copy dirty rect from backBuf to LFB.
|
|
On DOS, each scanline uses <code>rep movsd</code> for near-optimal
|
|
aligned 32-bit writes over the PCI bus.</dd>
|
|
|
|
<dt>Optimized Memory Spans</dt>
|
|
<dd>Six functions: <code>platformSpanFill8/16/32()</code> and
|
|
<code>platformSpanCopy8/16/32()</code>. Called once per scanline of
|
|
every rectangle fill, blit, and text draw. On DOS these use inline
|
|
assembly for critical inner loops
|
|
<code>memset</code>/<code>memcpy</code>.</dd>
|
|
|
|
<dt>Mouse Input</dt>
|
|
<dd>Polling model. <code>platformMousePoll()</code> returns position and
|
|
button bitmask. Wheel support via CuteMouse API.</dd>
|
|
|
|
<dt>Keyboard Input</dt>
|
|
<dd><code>platformKeyboardRead()</code> -- non-blocking key read.<br>
|
|
<code>platformKeyUpRead()</code> -- key release detection (requires
|
|
INT 9 hook on DOS).<br>
|
|
<code>platformAltScanToChar()</code> -- scancode-to-ASCII lookup for
|
|
Alt+key combinations.</dd>
|
|
|
|
<dt>Crash Recovery</dt>
|
|
<dd><code>platformInstallCrashHandler()</code> -- signal handlers +
|
|
<code>longjmp</code> for fault tolerance.</dd>
|
|
|
|
<dt>DXE Support</dt>
|
|
<dd><code>platformRegisterDxeExports()</code> -- register C runtime and
|
|
platform symbols for DXE resolution.<br>
|
|
<code>platformRegisterSymOverrides()</code> -- register function
|
|
pointer overrides for module loader.</dd>
|
|
</dl>
|
|
|
|
<!-- =================================================================== -->
|
|
<h2 id="build">11. Build System</h2>
|
|
|
|
<h3>Cross-Compilation</h3>
|
|
|
|
<p>DVX is cross-compiled from Linux using a DJGPP cross-compiler
|
|
(<code>i586-pc-msdosdjgpp-gcc</code>). The top-level <code>Makefile</code>
|
|
orchestrates building all subsystems in dependency order.</p>
|
|
|
|
<pre><code> make -- build everything
|
|
./mkcd.sh -- build + create ISO for 86Box
|
|
</code></pre>
|
|
|
|
<h3>Build Targets</h3>
|
|
|
|
<pre><code> all: core tasks loader texthelp listhelp tools widgets shell taskmgr serial sql apps
|
|
</code></pre>
|
|
|
|
<table>
|
|
<tr><th>Target</th><th>Output</th><th>Description</th></tr>
|
|
<tr><td><code>core</code></td><td><code>bin/libs/libdvx.lib</code></td>
|
|
<td>GUI core library (draw, comp, wm, app, widget infrastructure)</td></tr>
|
|
<tr><td><code>tasks</code></td><td><code>bin/libs/libtasks.lib</code></td>
|
|
<td>Cooperative task switcher</td></tr>
|
|
<tr><td><code>loader</code></td><td><code>bin/dvx.exe</code></td>
|
|
<td>Bootstrap loader (the DOS executable)</td></tr>
|
|
<tr><td><code>widgets</code></td><td><code>bin/widgets/*.wgt</code></td>
|
|
<td>29 widget type plugins</td></tr>
|
|
<tr><td><code>shell</code></td><td><code>bin/libs/dvxshell.lib</code></td>
|
|
<td>DVX Shell (app management, desktop)</td></tr>
|
|
<tr><td><code>taskmgr</code></td><td><code>bin/libs/taskmgr.lib</code></td>
|
|
<td>Task Manager (loaded as a separate DXE)</td></tr>
|
|
<tr><td><code>texthelp</code></td><td>shared library</td>
|
|
<td>Shared text editing helpers (clipboard, word boundaries)</td></tr>
|
|
<tr><td><code>listhelp</code></td><td>shared library</td>
|
|
<td>Shared dropdown/list helpers</td></tr>
|
|
<tr><td><code>apps</code></td><td><code>bin/apps/*/*.app</code></td>
|
|
<td>Application modules (progman, notepad, clock, etc.)</td></tr>
|
|
<tr><td><code>tools</code></td><td><code>bin/dvxres</code></td>
|
|
<td>Resource compiler (runs on Linux, builds resource sections into DXEs)</td></tr>
|
|
<tr><td><code>serial</code></td><td>serial DXE libs</td>
|
|
<td>UART driver, HDLC packets, security, seclink</td></tr>
|
|
<tr><td><code>sql</code></td><td>SQL DXE lib</td>
|
|
<td>SQLite integration</td></tr>
|
|
</table>
|
|
|
|
<h3>DXE3 Build Process</h3>
|
|
<p>Each DXE module is compiled to an object file with GCC, then linked
|
|
with <code>dxe3gen</code>:</p>
|
|
<pre><code> # Compile
|
|
i586-pc-msdosdjgpp-gcc -O2 -march=i486 -mtune=i586 -c -o widget.o widget.c
|
|
|
|
# Link as DXE with exported symbols
|
|
dxe3gen -o widget.wgt -E _wgtRegister -U widget.o
|
|
|
|
# Optionally append resources
|
|
dvxres build widget.wgt widget.res
|
|
</code></pre>
|
|
|
|
<p>The <code>-E</code> flag specifies exported symbols (prefixed with
|
|
underscore per DJGPP convention). <code>-U</code> marks unresolved symbols
|
|
as OK (they'll be resolved at load time from previously loaded DXEs).</p>
|
|
|
|
<h3>Deployment (mkcd.sh)</h3>
|
|
<ol>
|
|
<li>Runs <code>make all</code>.</li>
|
|
<li>Verifies critical outputs exist (<code>dvx.exe</code>,
|
|
<code>libtasks.lib</code>, <code>libdvx.lib</code>,
|
|
<code>dvxshell.lib</code>).</li>
|
|
<li>Counts widget modules.</li>
|
|
<li>Creates an ISO 9660 image from <code>bin/</code> using
|
|
<code>mkisofs</code>:
|
|
<ul>
|
|
<li><code>-iso-level 1</code>: strict 8.3 filenames for DOS</li>
|
|
<li><code>-J</code>: Joliet extensions for long names</li>
|
|
<li><code>-V DVX</code>: volume label</li>
|
|
</ul>
|
|
</li>
|
|
<li>Places the ISO at
|
|
<code>~/.var/app/net._86box._86Box/data/86Box/dvx.iso</code> for
|
|
86Box to mount as CD-ROM.</li>
|
|
</ol>
|
|
|
|
<h3>Compiler Flags</h3>
|
|
<pre><code> -O2 Optimization level 2
|
|
-march=i486 486 instruction set baseline
|
|
-mtune=i586 Optimize scheduling for Pentium
|
|
-Wall -Wextra Full warnings
|
|
</code></pre>
|
|
|
|
<h3>Directory Layout</h3>
|
|
<pre><code> dvxgui/
|
|
+-- core/ Core library sources (dvxVideo, dvxDraw, dvxComp, dvxWm, dvxApp, widget infra)
|
|
| +-- platform/ Platform abstraction (dvxPlatform.h, dvxPlatformDos.c)
|
|
| +-- thirdparty/ stb_image, stb_ds, stb_image_write
|
|
+-- loader/ Bootstrap loader (dvx.exe)
|
|
+-- tasks/ Cooperative task switcher (libtasks.lib)
|
|
+-- shell/ DVX Shell (dvxshell.lib)
|
|
+-- widgets/ Widget DXE modules (*.wgt), each in its own subdirectory
|
|
| +-- box/ VBox/HBox layout containers
|
|
| +-- button/ Push button
|
|
| +-- textInput/ Text entry field
|
|
| +-- listView/ Multi-column list
|
|
| +-- ... (29 widget types total)
|
|
+-- texthelp/ Shared text editing helpers
|
|
+-- listhelp/ Shared dropdown/list helpers
|
|
+-- apps/ Application DXE modules (*.app)
|
|
| +-- progman/ Program Manager (desktop)
|
|
| +-- notepad/ Text editor
|
|
| +-- cpanel/ Control Panel
|
|
| +-- imgview/ Image viewer
|
|
| +-- clock/ Clock
|
|
| +-- dvxdemo/ Demo / showcase app
|
|
| +-- dvxbasic/ DVX BASIC compiler and VM
|
|
+-- tools/ Build tools (dvxres resource compiler)
|
|
+-- rs232/ ISR-driven UART driver
|
|
+-- packet/ HDLC framing, CRC-16, sliding window
|
|
+-- security/ DH key exchange, XTEA cipher, DRBG RNG
|
|
+-- seclink/ Encrypted channel wrapper
|
|
+-- serial/ Combined serial stack DXE
|
|
+-- proxy/ Linux proxy (86Box <-> secLink <-> telnet)
|
|
+-- sql/ SQLite integration
|
|
+-- bin/ Build output (dvx.exe, libs/, widgets/, apps/, config/)
|
|
+-- obj/ Intermediate object files
|
|
+-- docs/ Documentation
|
|
</code></pre>
|
|
|
|
<hr>
|
|
<p><em>Generated 2026-04-06. Source: DVX GUI codebase headers and design documents.</em></p>
|
|
|
|
</body>
|
|
</html>
|