14 KiB
DVX Shell Applications
Every DVX application is a DXE3 module packaged as a .app file,
installed under bin/apps/kpunch/<name>/<name>.app. The Program
Manager scans this directory at startup and displays each discovered
app as a launchable icon on the desktop.
This directory holds the source for the bundled applications plus the BASIC-based sample apps. Two flavours of app live side by side:
- C apps -- written directly against the DVX SDK headers,
compiled to a DXE3 by
dxe3gen. Seeprogman/,clock/,dvxdemo/,cpanel/,dvxhelp/. - BASIC apps --
.dbpprojects compiled to.appfiles by the host-sidebascomp. The compiler links the BASIC bytecode into a copy ofbasstub.app, which acts as the runtime host. Seeiconed/,notepad/,imgview/,basicdemo/,resedit/,dvxhelp/helpedit/.
The rest of this document covers writing a C app against the SDK.
For BASIC apps, see dvxbasic/README.md.
DXE App Contract
Every .app binary exports two required symbols and one optional
symbol:
AppDescriptorT appDescriptor; // required
int32_t appMain(DxeAppContextT *ctx); // required
void appShutdown(void); // optional
appDescriptor
A statically-initialised struct read by the shell at load time to decide how to launch the app:
typedef struct {
char name[SHELL_APP_NAME_MAX]; // display name (<= 64 chars)
bool hasMainLoop; // see below
bool multiInstance; // may have multiple copies open
int32_t stackSize; // SHELL_STACK_DEFAULT or byte count
int32_t priority; // TS_PRIORITY_* for main-loop apps
} AppDescriptorT;
Example (from clock/clock.c):
AppDescriptorT appDescriptor = {
.name = "Clock",
.hasMainLoop = true,
.multiInstance = true,
.stackSize = SHELL_STACK_DEFAULT,
.priority = TS_PRIORITY_LOW
};
appMain
Entry point. The shell calls it with a DxeAppContextT that exposes
the shell's GUI context, the app's ID, its install directory, a
writable config directory, launch arguments, and a help-topic query
callback for F1.
Returning from appMain signals that the app has finished; the
shell unloads the DXE, frees per-app memory, and reclaims the app
slot.
appShutdown
Called by the shell when the app is force-killed (by the Task
Manager) or when the shell is shutting down with this app still
running. Main-loop apps use it to set a flag that their main loop
observes, so the loop exits cleanly and appMain can return.
App Types
Callback-only apps (hasMainLoop = false)
appMain creates windows, registers callbacks, and returns 0. The
shell drives all further work by invoking those callbacks in
response to user input and timers. No dedicated task is allocated;
no per-app stack is consumed. The app's lifetime ends when the last
window closes (or when every callback has released all references).
Use this pattern for event-driven UI: Notepad, Program Manager, DVX Demo, Control Panel, Image Viewer.
Main-loop apps (hasMainLoop = true)
The shell creates a cooperative task for the app and calls
appMain from inside it. appMain runs a loop that calls
tsYield() periodically to share the CPU. Exit by breaking out of
the loop and returning.
Use this pattern when the app needs continuous background work that does not map cleanly onto event callbacks: Clock (polls the system clock every second), terminal emulators, games.
Resource Conventions
Apps attach resources to their .app binary using dvxres build
(see src/tools/README.md). The standard resource names are:
| Name | Type | Meaning |
|---|---|---|
icon32 |
icon | 32x32 BMP shown in Program Manager and the Task Manager. |
name |
text | Human-readable display name (overrides appDescriptor.name for UI where available). |
author |
text | Author / maintainer name. |
publisher |
text | Publisher or studio. |
copyright |
text | Copyright notice. |
version |
text | Version string, free-form. |
description |
text | One-sentence description shown in About dialogs. |
helpfile |
text | Optional relative path to a .hlp file for F1 context help. |
Additional application-specific resources may be attached with any
unique name. The runtime reads them via
dvxResOpen(appPath) / dvxResRead(handle, name, &size) /
dvxResClose(handle).
Typical .res manifest:
# clock.res
icon32 icon icon32.bmp
name text "Clock"
author text "Scott Duensing"
copyright text "Copyright 2026 Scott Duensing"
publisher text "Kangaroo Punch Studios"
description text "Digital clock with date display"
Bundled Applications
Program Manager (progman)
| File | apps/kpunch/progman/progman.app |
| Type | Callback-only |
| Multi-instance | No |
The desktop. Recursively scans apps/ for .app files and displays
them as a launchable grid with icons, names, and publishers. Double
click or Enter to launch. Includes a Help menu with the system help
viewer and the About / System Info dialog. Registers with
shellRegisterDesktopUpdate() so the grid refreshes when apps are
loaded, terminated, or crash.
Widget headers used: box/box.h, button/button.h, label/label.h,
statusBar/statBar.h, textInput/textInpt.h, imageButton/imgBtn.h,
scrollPane/scrlPane.h, wrapBox/wrapBox.h.
Notepad (notepad, BASIC)
| File | apps/kpunch/notepad/notepad.app |
| Type | BASIC (main-loop via basstub) |
| Multi-instance | No |
Plain-text editor with File menu (New, Open, Save, Save As) and Edit
menu (Cut, Copy, Paste, Select All). Built from a BASIC project
(notepad.dbp + notepad.frm); demonstrates the form designer,
TextInput widget, and common dialog integration.
Clock (clock)
| File | apps/kpunch/clock/clock.app |
| Type | Main-loop |
| Multi-instance | Yes |
Digital clock showing time and date. Polls the system clock every
second and invalidates the window to trigger a repaint. Uses the raw
onPaint callback (no widgets) to draw centered text. Reference
implementation for main-loop apps.
DVX Demo (dvxdemo)
| File | apps/kpunch/dvxdemo/dvxdemo.app |
| Type | Callback-only |
| Multi-instance | No |
Widget toolkit showcase. Opens multiple windows demonstrating virtually every widget type:
- Main window -- raw paint callbacks (gradients, patterns, text)
- Widget demo -- form widgets (TextInput, Checkbox, Radio, ListBox)
- Controls window -- tabbed advanced widgets (Dropdown, ProgressBar, Slider, Spinner, TreeView, ListView, ScrollPane, Toolbar, Canvas, Splitter, Image)
- Terminal window -- AnsiTerm widget
Resources include logo.bmp, new.bmp, open.bmp, sample.bmp,
save.bmp. Reference implementation for widget-based UIs.
Control Panel (cpanel)
| File | apps/kpunch/cpanel/cpanel.app |
| Type | Callback-only |
| Multi-instance | No |
System configuration with four tabs:
- Mouse -- scroll direction, wheel speed, double-click speed, acceleration, cursor speed
- Colors -- every system colour with live preview; theme load and save
- Desktop -- wallpaper image and display mode
- Video -- resolution and colour depth switching
Changes preview live. OK writes to CONFIG/DVX.INI; Cancel reverts
to the snapshot taken when the panel opened.
Image Viewer (imgview, BASIC)
| File | apps/kpunch/imgview/imgview.app |
| Type | BASIC (main-loop via basstub) |
| Multi-instance | No |
Displays BMP, PNG, JPEG, and GIF images scaled to fit the window with aspect ratio preserved. Resize to zoom. Open via the File menu or via launch arguments. Built from a BASIC project using the Canvas widget.
DVX BASIC (dvxbasic)
| File | apps/kpunch/dvxbasic/dvxbasic.app |
| Type | Callback-only |
| Multi-instance | No |
Visual Basic 3 compatible IDE: form designer, per-procedure code
editor, project manager, compiler, and runtime VM. See
dvxbasic/README.md for a detailed architecture description.
dvxbasic/ also builds:
bin/libs/kpunch/basrt/basrt.lib-- the BASIC runtime (VM + values) as a separately loadable library, so compiled BASIC apps do not carry their own copy of the runtime.bin/apps/kpunch/dvxbasic/basstub.app-- the stub used as the template for every compiled BASIC app.
DVX Help Viewer (dvxhelp)
| File | apps/kpunch/dvxhelp/dvxhelp.app |
| Type | Callback-only |
| Multi-instance | Yes |
Renders compiled .hlp files produced by dvxhlpc. Supports table
of contents, keyword index, full-text search (trigram), hyperlinks,
and inline images.
Icon Editor (iconed, BASIC)
| File | apps/kpunch/iconed/iconed.app |
| Type | BASIC (main-loop via basstub) |
| Multi-instance | No |
Paint-program-style editor for creating 32x32 BMP icons. Pen / eraser / fill tools, 16-colour palette, BMP save / load.
Help Editor (helpedit, BASIC)
| File | apps/kpunch/dvxhelp/helpedit.app |
| Type | BASIC (main-loop via basstub) |
| Multi-instance | No |
Editor for .dhs help source files with syntax-aware controls. Runs
the compiled system help viewer by default for live preview.
Resource Editor (resedit, BASIC)
| File | apps/kpunch/resedit/resedit.app |
| Type | BASIC (main-loop via basstub) |
| Multi-instance | No |
GUI wrapper around dvxres: open a .app / .wgt / .lib,
browse its resources, add, replace, extract, or remove them.
BASIC Demo (basicdemo, BASIC)
| File | apps/kpunch/basicdemo/basicdemo.app |
| Type | BASIC (main-loop via basstub) |
| Multi-instance | No |
Gallery of short BASIC programs demonstrating the language and the form designer. Intended as sample source for reading.
Build
make # build every app (C apps + BASIC apps)
make <appname> # build a single app
make clean # remove all app build artifacts
The apps/kpunch/Makefile orchestrates both C and BASIC builds:
- C apps compile each
<app>/<app>.cto an object file, rundxe3gen -Uon it to produce<app>.app, then attach resources withdvxres buildif a.resmanifest exists. - BASIC apps run
bascomp <app>.dbp -o <app>.app -release, which handles project-file parsing, compilation, resource attachment, and linking intobasstub.app.
Build output goes to bin/apps/kpunch/<app>/<app>.app.
Writing a New C App
Minimal skeleton:
#include "dvxApp.h"
#include "dvxWgt.h"
#include "shellApp.h"
#include <stdint.h>
#include <stdbool.h>
// Prototypes
static int32_t appMainImpl(DxeAppContextT *ctx);
static void onClose(WindowT *win);
// Required descriptor
AppDescriptorT appDescriptor = {
.name = "My App",
.hasMainLoop = false,
.multiInstance = false,
.stackSize = SHELL_STACK_DEFAULT,
.priority = 0
};
static void onClose(WindowT *win) {
(void)win;
// Callback-only apps: nothing to do; the shell reaps us when
// the last window closes.
}
int32_t appMain(DxeAppContextT *ctx) {
return appMainImpl(ctx);
}
static int32_t appMainImpl(DxeAppContextT *ctx) {
AppContextT *ac = ctx->shellCtx;
WindowT *win = dvxCreateWindow(ac, appDescriptor.name, 100, 100, 320, 240, true);
if (!win) {
return -1;
}
win->onClose = onClose;
return 0;
}
Add a Makefile target that mirrors the existing apps (see
apps/kpunch/Makefile for the pattern), drop a .res manifest next
to the source, and provide a 32x32 icon32.bmp. make <app> should
then produce bin/apps/kpunch/<app>/<app>.app.
Testing Locally
After make, the app is deployed in-tree under bin/apps/kpunch/.
Launch the full system (bin/dvx.exe) and the Program Manager picks
up the new app automatically on the next boot.
To iterate quickly: rebuild the single app, restart DVX, and launch
it. The log at bin/DVX.LOG records load errors, missing
dependencies, and per-app crash diagnostics.
Files
apps/kpunch/
Makefile top-level app build
README.md this file
# C apps
progman/
progman.c Program Manager
dvxhelp.hcf help-compiler config (system reference)
clock/
clock.c digital clock (main-loop reference)
clock.res
icon32.bmp
dvxdemo/
dvxdemo.c widget showcase
dvxdemo.res
icon32.bmp
logo.bmp / new.bmp / open.bmp / sample.bmp / save.bmp
cpanel/
cpanel.c Control Panel
cpanel.res
icon32.bmp
dvxhelp/
dvxhelp.c help viewer
dvxhelp.res
help.dhs source for the dvxhelp app's own help
hlpformat.h binary format shared with the compiler
sample.dhs small sample source
icon32.bmp
helpedit/ BASIC project: help editor
helpedit.dbp
helpedit.frm
ICON32.BMP
# BASIC apps
iconed/
iconed.dbp
iconed.frm
ICON32.BMP
notepad/
notepad.dbp
notepad.frm
ICON32.BMP
imgview/
imgview.dbp
imgview.frm
ICON32.BMP
basicdemo/
basicdemo.dbp
basicdemo.frm
ICON32.BMP
resedit/
resedit.dbp
resedit.frm
ICON32.BMP
dvxbasic/ see dvxbasic/README.md
compiler/ lexer, parser, codegen, strip, obfuscate
runtime/ VM + value system
formrt/ form runtime (BASIC <-> DVX widgets)
ide/ IDE front end
stub/ bascomp + basstub
...