DVX_GUI/src/apps/kpunch/README.md

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. See progman/, clock/, dvxdemo/, cpanel/, dvxhelp/.
  • BASIC apps -- .dbp projects compiled to .app files by the host-side bascomp. The compiler links the BASIC bytecode into a copy of basstub.app, which acts as the runtime host. See iconed/, 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>.c to an object file, run dxe3gen -U on it to produce <app>.app, then attach resources with dvxres build if a .res manifest exists.
  • BASIC apps run bascomp <app>.dbp -o <app>.app -release, which handles project-file parsing, compilation, resource attachment, and linking into basstub.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
    ...