Much improved printing. More sound devices supported. Sound recording.

This commit is contained in:
Scott Duensing 2026-10-17 15:55:36 -05:00
parent f8ec4586e3
commit aecc93b7ab
615 changed files with 49876 additions and 2900 deletions

View file

@ -39,11 +39,11 @@
LIBS = $(sort $(notdir $(patsubst %/Makefile,%,$(wildcard src/libs/kpunch/*/Makefile))))
CORE_LIBS = libdvx libtasks
.PHONY: all clean $(LIBS) loader widgets apps tools installer dist deploy-helpsrc compile-help deploy-sdk test test-quick test-asan test-host test-modules test-samples coverage test-qa test-fuzz bench bench-compare
.PHONY: all clean $(LIBS) loader widgets apps savers tools installer dist deploy-helpsrc compile-help deploy-sdk test test-quick test-asan test-host test-modules test-samples coverage test-qa test-fuzz bench bench-compare
# Every build ends by making the release media in dist/ (a second or
# two), so dist/ always holds the latest DVX.
all: $(LIBS) loader tools widgets apps installer deploy-helpsrc compile-help deploy-sdk
all: $(LIBS) loader tools widgets apps savers installer deploy-helpsrc compile-help deploy-sdk
src/installer/mkDist.sh $(or $(FLOPPY),1.44M)
$(LIBS):
@ -77,6 +77,11 @@ dist: all
apps: libdvx libtasks dvxshell tools
$(MAKE) -C src/apps/kpunch
# The screen savers (bin/shared/savers): BASIC ones need bascomp, which
# the apps build makes.
savers: apps
$(MAKE) -C src/savers/kpunch
# Copies help sources into the module directories under bin/, so every
# module that owns one must be built first.
deploy-helpsrc: $(LIBS) widgets apps tools
@ -132,7 +137,7 @@ test-samples:
# Builds every module first so the check sees the current binaries.
BASIC_STUB = obj/dvxbasic/basstub.app
test-modules: $(LIBS) loader widgets apps
test-modules: $(LIBS) loader widgets apps savers
src/test/shell/checkDxeExports.sh . $(BASIC_STUB)
# BASIC compiler / VM benchmarks (src/test/basic/basBench.c, programs in
@ -288,6 +293,7 @@ clean:
$(MAKE) -C src/loader clean
$(MAKE) -C src/widgets/kpunch clean
$(MAKE) -C src/apps/kpunch clean
$(MAKE) -C src/savers/kpunch clean
$(MAKE) -C src/tools clean
$(MAKE) -C src/tools/proxy clean
$(MAKE) -C src/installer clean

View file

@ -24,3 +24,11 @@ CTL = apps/kpunch/dvxbasic/dvxbasic.app
HLP = apps/kpunch/dvxhelp/dvxhelp.app
DHS = apps/kpunch/dvxhelp/helpedit.app
DPK = apps/kpunch/software/software.app
MOD = apps/kpunch/player/player.app
S3M = apps/kpunch/player/player.app
XM = apps/kpunch/player/player.app
IT = apps/kpunch/player/player.app
MID = apps/kpunch/player/player.app
RMI = apps/kpunch/player/player.app
WAV = apps/kpunch/player/player.app
VOC = apps/kpunch/player/player.app

BIN
config/DOSPROG.BMP (Stored with Git LFS) Normal file

Binary file not shown.

View file

@ -16,6 +16,7 @@ the shipped list.
|-------------|-------------|-------------|
| `dvx.ini` | `bin/system/DVX.INI` | The settings a new user starts with |
| `ASSOC.INI` | `bin/system/ASSOC.INI` | File associations: which program opens each document type (shellAssoc.h; changed on the Control Panel's File Types page, in the user's ASSOC.INI) |
| `DOSPROG.BMP` | `bin/system/DOSPROG.BMP` | The icon of a DOS program (EXE, COM, BAT) in Program Manager when it has no picture of its own (SHELL_DOS_ICON, shellProg.h) |
| `themes/cde.thm` | `bin/shared/themes/cde.thm` | CDE color theme |
| `themes/geos.thm` | `bin/shared/themes/geos.thm` | GEOS Ensemble theme |
| `themes/hotdog.thm` | `bin/shared/themes/hotdog.thm` | Hot Dog Stand theme |
@ -99,6 +100,8 @@ compiled-in defaults.
|-----|---------|--------|-------------|
| `wallpaper` | (none) | file path | Path to wallpaper image |
| `mode` | stretch | stretch, tile, center | Wallpaper display mode |
| `saver` | (none) | file name | Screen saver: a program in SHARED\SAVERS or the user's SAVERS |
| `saverWait` | 10 | 1-60 | Minutes with no key or mouse input before the screen saver starts |
### [network] Section
@ -125,9 +128,11 @@ as a whole in favour of the defaults.
| Key | Default | Values | Description |
|-----|---------|--------|-------------|
| `port` | LPT1 | LPT1, LPT2, LPT3, FILE | Where printed output goes |
| `port` | LPT1 | LPT1, LPT2, LPT3, COM1, COM2, COM3, COM4, FILE | Where printed output goes |
| `baud` | 9600 | 300, 1200, 2400, 4800, 9600, 19200, 38400 | A serial printer's speed (port COM1-COM4) |
| `handshake` | dtrdsr | none, xonxoff, rtscts, dtrdsr | How a serial printer holds the computer back: XON / XOFF characters, or its ready line on the computer's CTS or DSR (Apple's ImageWriter cable) |
| `file` | PRINTER.PRN | file path | The file used with port = FILE |
| `model` | text | text, epson9, epson24, laserjet | Printer model; all but text print pictures |
| `model` | text | text, epson9, epson24, laserjet, laserjet300, epson9color, epson24color, deskjet500c, deskjetcolor, postscript, postscriptcolor, imagewriter, imagewritercolor | Printer model; all but text print pictures; epson9color, epson24color, deskjet500c, deskjetcolor, postscriptcolor, and imagewritercolor in color |
| `linesPerPage` | 0 | 0, 10-200 | Lines per page; 0 = the model's usual length (66, laser 60) |
| `columns` | 80 | 20-255 | Characters across the page |
| `marginTop`, `marginBottom` | 3 | lines | Top and bottom margins (header / footer in their middle line) |

View file

@ -65,9 +65,19 @@ user =
password =
; Printer settings (Control Panel's Printer page and File > Page Setup).
; port: LPT1, LPT2, LPT3 or FILE (print into the file named by file)
; port: LPT1, LPT2, LPT3, COM1 to COM4 (a serial printer), or FILE
; (print into the file named by file)
; baud, handshake: a serial printer's speed (300 to 38400) and how it
; holds the computer back: none, xonxoff, rtscts (its ready line on
; CTS), or dtrdsr (on DSR, as Apple's ImageWriter cable wires it)
; model: text (any printer, text only), epson9, epson24 (Epson ESC/P
; dot matrix) or laserjet (HP PCL); all but text print pictures
; dot matrix), laserjet (HP PCL, 150 dpi), laserjet300 (HP
; LaserJet III, DeskJet, and later; 300 dpi), epson9color,
; epson24color (Epson with a color ribbon), deskjet500c,
; deskjetcolor (DeskJet 550C and later), postscript,
; postscriptcolor, imagewriter, or imagewritercolor (Apple
; ImageWriter II); all but text print pictures, the color ones in
; color
; linesPerPage: 0 = the printer's usual page length (66, laser 60)
; columns: characters across the page; margins in lines (top, bottom)
; and characters (left, right)
@ -88,10 +98,14 @@ tabWidth = 8
wrap = true
header = &f
footer = Page &p
baud = 9600
handshake = dtrdsr
; Sound settings.
; driver: auto (find the sound hardware), sb (Sound Blaster family),
; speaker (PC speaker) or null (no sound)
; driver: auto (find the sound hardware), wss (Windows Sound System),
; sb (Sound Blaster family), gus (Gravis UltraSound), lpt (a
; DAC on the printer port), speaker (PC speaker) or null (no
; sound)
; rate: mixing rate in Hz (4000-48000, default 22050); the sound card may
; run slightly faster or slower
; bits, channels: 0 = the best the sound card can do, or 8 / 16 bits and
@ -103,17 +117,37 @@ footer = Page &p
; the computer's time); false = tones only
; fmTones: true = square and triangle tones play on the music synthesizer
; chip when there is one; false = always mixed
; midi: where MIDI music plays: auto (the synthesizer chip, else a
; built-in synthesizer), mpu401 (an external synthesizer on the
; MIDI port), fm (the chip) or software (the built-in synthesizer)
; midi: where MIDI music plays: auto (a Gravis UltraSound's or Sound
; Blaster AWE's recorded instruments, else the synthesizer chip,
; else a built-in synthesizer), mpu401 (an external synthesizer on
; the MIDI port), fm (the chip), software (the built-in
; synthesizer) or softwave (the SoundFont played by the computer)
; midiIn: where MIDI input (a MIDI keyboard) comes from: none or mpu401
; (the MIDI port, shared with MIDI music when midi = mpu401 too)
; modules: where music modules (MOD, S3M, XM, IT) play: wavetable (a
; Gravis UltraSound's or Sound Blaster AWE's own voices when no
; other music plays there and the module fits, else mixed by
; the computer) or software (always mixed by the computer)
; mpuMode: what is on the MIDI port: gm (a General MIDI synthesizer),
; mt32 (a Roland MT-32) or raw (send music unchanged)
; Optional: oplPort (default 388) and mpuPort (default 330), in hex;
; midiBank = the instrument bank for MIDI music (OP2 format): its name in
; SHARED\BANKS or USER\BANKS (an add-on's as VENDOR\NAME), or a path from
; the DVX folder; not set, the bundled one. Control Panel picks it.
; the DVX folder; not set, the bundled one. Control Panel picks it;
; each MIDI music reads it as it starts.
; soundFont = the recorded instruments (a SoundFont, .SF2 or .SBK) for a
; Gravis UltraSound, a Sound Blaster AWE and softwave, named as midiBank
; is, or the path of a Gravis UltraSound's ULTRASND.INI (its patches);
; not set, KPUNCH\DVXGM.SF2 (an add-on), else the card's own.
; The Sound Blaster's port, IRQ and DMA come from the BLASTER setting (for
; example SET BLASTER=A220 I5 D1 H5 in AUTOEXEC.BAT).
; example SET BLASTER=A220 I5 D1 H5 in AUTOEXEC.BAT; an AWE adds E620),
; the Gravis UltraSound's from ULTRASND (SET ULTRASND=220,1,1,11,5).
; Optional: gusVoices (14-32, default 28: fewer play at a higher rate);
; wssPort (530, 604, E80 or F40, hex), wssIrq (7, 9, 10 or 11, default 7)
; and wssDma (0, 1 or 3, default 1) for a Windows Sound System card;
; lptDac (auto, covox, disney or stereo; auto finds a Disney Sound Source
; or a Stereo-on-1, a Covox must be named) and lptPort (hex, default
; LPT1) for a DAC on the printer port.
[audio]
driver = auto
@ -125,6 +159,8 @@ volume = 100
speakerPcm = false
fmTones = true
midi = auto
midiIn = none
modules = wavetable
mpuMode = gm
; Desktop sounds (Control Panel's Sounds page): the sound file (WAV or VOC)

View file

@ -107,6 +107,7 @@ img { max-width: 100%; }
<li><a href="#lang.sql">SQL Functions</a></li>
<li><a href="#lang.app">App Object</a></li>
<li><a href="#lang.clipboard">Clipboard Object</a></li>
<li><a href="#lang.printerobj">Printer Object</a></li>
<li><a href="#lang.screenobj">Screen Object</a></li>
<li><a href="#lang.ini">INI Functions</a></li>
<li><a href="#lang.constants">Predefined Constants</a></li>
@ -455,6 +456,7 @@ img { max-width: 100%; }
<li><a href="#ctrl.drawing">Drawing Methods</a></li>
<li><a href="#ctrl.drawing">DrawScrollArrow</a></li>
<li><a href="#ctrl.drawing">DrawScrollBar</a></li>
<li><a href="#ctrl.drawing">DrawStyle</a></li>
<li><a href="#ctrl.drawing">DrawWidth</a></li>
<li><a href="#ctrl.dropdown">DropDown</a></li>
<li><a href="#ide.overview">DVX BASIC</a></li>
@ -473,6 +475,7 @@ img { max-width: 100%; }
<li><a href="#lang.procedures">END SUB</a></li>
<li><a href="#lang.declarations">END TYPE</a></li>
<li><a href="#lang.classes">END WITH</a></li>
<li><a href="#lang.printerobj">EndDoc</a></li>
<li><a href="#lang.declarations">ENUM</a></li>
<li><a href="#lang.func.misc">ENVIRON$</a></li>
<li><a href="#lang.func.fileio">EOF</a></li>
@ -701,6 +704,7 @@ img { max-width: 100%; }
<li><a href="#lang.clipboard">Key Codes</a></li>
<li><a href="#ide.shortcuts">Keyboard Shortcuts</a></li>
<li><a href="#lang.filesystem">KILL</a></li>
<li><a href="#lang.printerobj">KillDoc</a></li>
<li><a href="#ctrl.label">Label</a></li>
<li><a href="#lang.flow">Labels</a></li>
<li><a href="#lang.classes">Late Binding</a></li>
@ -771,9 +775,16 @@ img { max-width: 100%; }
<li><a href="#lang.sound">MF</a></li>
<li><a href="#lang.func.string">MID$</a></li>
<li><a href="#lang.runtime">MIDI</a></li>
<li><a href="#lang.runtime">MIDI keyboard</a></li>
<li><a href="#lang.runtime">MidiAcquire</a></li>
<li><a href="#lang.runtime">MidiInClock</a></li>
<li><a href="#lang.runtime">MidiInMessage</a></li>
<li><a href="#lang.runtime">MidiInOpen</a></li>
<li><a href="#lang.runtime">MidiInTime</a></li>
<li><a href="#lang.runtime">MidiPortInfo$</a></li>
<li><a href="#lang.runtime">MidiPut</a></li>
<li><a href="#lang.runtime">MidiRecordNew</a></li>
<li><a href="#lang.runtime">MidiRecordSave</a></li>
<li><a href="#ide.changes">Migration</a></li>
<li><a href="#ctrl.hscrollbar">Min</a></li>
<li><a href="#lang.func.date">MINUTE</a></li>
@ -805,9 +816,12 @@ img { max-width: 100%; }
<li><a href="#lang.runtime">MusicInfo$</a></li>
<li><a href="#lang.runtime">MusicLength</a></li>
<li><a href="#lang.runtime">MusicLoad</a></li>
<li><a href="#lang.runtime">MusicLoadMacro</a></li>
<li><a href="#lang.runtime">MusicMidiOpen</a></li>
<li><a href="#lang.runtime">MusicMidiSend</a></li>
<li><a href="#lang.runtime">MusicNoteOff</a></li>
<li><a href="#lang.runtime">MusicNoteOn</a></li>
<li><a href="#lang.runtime">MusicPatchSet$</a></li>
<li><a href="#lang.runtime">MusicPause</a></li>
<li><a href="#lang.runtime">MusicPitchBend</a></li>
<li><a href="#lang.runtime">MusicPlay</a></li>
@ -815,7 +829,9 @@ img { max-width: 100%; }
<li><a href="#lang.runtime">MusicPosition</a></li>
<li><a href="#lang.runtime">MusicProgram</a></li>
<li><a href="#lang.runtime">MusicResume</a></li>
<li><a href="#lang.runtime">MusicRomBank$</a></li>
<li><a href="#lang.runtime">MusicSeek</a></li>
<li><a href="#lang.runtime">MusicSetBank</a></li>
<li><a href="#lang.runtime">MusicStop</a></li>
<li><a href="#lang.runtime">MusicVolume</a></li>
<li><a href="#lang.filesystem">NAME</a></li>
@ -830,6 +846,7 @@ img { max-width: 100%; }
<li><a href="#ide.menu.file">New UserControl</a></li>
<li><a href="#ide.usercontrols">New UserControl</a></li>
<li><a href="#ctrl.form">NewArgs</a></li>
<li><a href="#lang.printerobj">NewPage</a></li>
<li><a href="#lang.loops">NEXT</a></li>
<li><a href="#lang.operators">NOT</a></li>
<li><a href="#lang.declarations">Nothing</a></li>
@ -878,6 +895,7 @@ img { max-width: 100%; }
<li><a href="#ctrl.picturebox">PictureBox</a></li>
<li><a href="#lang.runtime">pkg.bas</a></li>
<li><a href="#lang.runtime">PkgBuild</a></li>
<li><a href="#lang.runtime">PkgFileOwner$</a></li>
<li><a href="#lang.runtime">PkgInstallStart</a></li>
<li><a href="#lang.runtime">PkgKeygen</a></li>
<li><a href="#lang.runtime">pkgnet.bas</a></li>
@ -924,6 +942,18 @@ img { max-width: 100%; }
<li><a href="#lang.runtime">print.bas</a></li>
<li><a href="#ctrl.drawing">PrintAccel</a></li>
<li><a href="#lang.runtime">PrintChoose</a></li>
<li><a href="#lang.printerobj">Printer Object</a></li>
<li><a href="#lang.printerobj">Printer.Circle</a></li>
<li><a href="#lang.printerobj">Printer.Copies</a></li>
<li><a href="#lang.printerobj">Printer.EndDoc</a></li>
<li><a href="#lang.printerobj">Printer.FontSize</a></li>
<li><a href="#lang.printerobj">Printer.KillDoc</a></li>
<li><a href="#lang.printerobj">Printer.Line</a></li>
<li><a href="#lang.printerobj">Printer.NewPage</a></li>
<li><a href="#lang.printerobj">Printer.Page</a></li>
<li><a href="#lang.printerobj">Printer.PaintPicture</a></li>
<li><a href="#lang.printerobj">Printer.Print</a></li>
<li><a href="#lang.printerobj">Printer.PSet</a></li>
<li><a href="#lang.runtime">PrintForm</a></li>
<li><a href="#lang.runtime">PrintPageSetting</a></li>
<li><a href="#lang.runtime">PrintPageSetup</a></li>
@ -971,7 +1001,10 @@ img { max-width: 100%; }
<li><a href="#lang.io">READ</a></li>
<li><a href="#ctrl.spinbutton">RealMode</a></li>
<li><a href="#ctrl.menus">Recent files menu</a></li>
<li><a href="#lang.runtime">Recording</a></li>
<li><a href="#ctrl.data">RecordSource</a></li>
<li><a href="#lang.runtime">RecordStart</a></li>
<li><a href="#lang.runtime">RecordStop</a></li>
<li><a href="#lang.declarations">REDIM</a></li>
<li><a href="#lang.classes">Reference Counting</a></li>
<li><a href="#ide.changes">Release Notes</a></li>
@ -1148,19 +1181,23 @@ img { max-width: 100%; }
<li><a href="#lang.runtime">SoundCaps</a></li>
<li><a href="#lang.runtime">SoundCreate</a></li>
<li><a href="#lang.runtime">SoundError$</a></li>
<li><a href="#lang.runtime">SoundFont</a></li>
<li><a href="#lang.runtime">SoundFree</a></li>
<li><a href="#lang.runtime">SoundGetVolume</a></li>
<li><a href="#lang.runtime">SoundInfo$</a></li>
<li><a href="#lang.runtime">SoundLength</a></li>
<li><a href="#lang.runtime">SoundLoad</a></li>
<li><a href="#lang.runtime">SoundPause</a></li>
<li><a href="#lang.runtime">SoundPlay</a></li>
<li><a href="#lang.runtime">SoundPlayEvent</a></li>
<li><a href="#lang.runtime">SoundPlaying</a></li>
<li><a href="#lang.runtime">SoundResume</a></li>
<li><a href="#lang.runtime">SoundSetFrequency</a></li>
<li><a href="#lang.runtime">SoundSetPan</a></li>
<li><a href="#lang.runtime">SoundSetPitch</a></li>
<li><a href="#lang.runtime">SoundSetVolume</a></li>
<li><a href="#lang.runtime">SoundStreamClose</a></li>
<li><a href="#lang.runtime">SoundStreamFlush</a></li>
<li><a href="#lang.runtime">SoundStreamOpen</a></li>
<li><a href="#lang.runtime">SoundStreamWrite</a></li>
<li><a href="#lang.runtime">SoundVolume</a></li>
@ -1318,15 +1355,22 @@ img { max-width: 100%; }
<li><a href="#lang.constants">vbCFText</a></li>
<li><a href="#lang.constants">vbCharacters</a></li>
<li><a href="#lang.constants">vbCritical</a></li>
<li><a href="#lang.constants">vbCross</a></li>
<li><a href="#ctrl.common.props">vbCrosshair</a></li>
<li><a href="#lang.clipboard">vbCtrlMask</a></li>
<li><a href="#lang.constants">vbCurrency</a></li>
<li><a href="#lang.constants">vbCyan</a></li>
<li><a href="#lang.constants">vbDash</a></li>
<li><a href="#lang.constants">vbDashDot</a></li>
<li><a href="#lang.constants">vbDashDotDot</a></li>
<li><a href="#lang.constants">vbDataObject</a></li>
<li><a href="#lang.constants">vbDate</a></li>
<li><a href="#lang.constants">vbDefault</a></li>
<li><a href="#lang.constants">vbDiagonalCross</a></li>
<li><a href="#lang.constants">vbDirectory</a></li>
<li><a href="#lang.constants">vbDot</a></li>
<li><a href="#lang.constants">vbDouble</a></li>
<li><a href="#lang.constants">vbDownwardDiagonal</a></li>
<li><a href="#lang.constants">vbEmpty</a></li>
<li><a href="#lang.constants">vbEndDrag</a></li>
<li><a href="#lang.constants">vbEnter</a></li>
@ -1336,6 +1380,8 @@ img { max-width: 100%; }
<li><a href="#lang.constants">vbFirstFullWeek</a></li>
<li><a href="#lang.constants">vbFirstJan1</a></li>
<li><a href="#lang.constants">vbFriday</a></li>
<li><a href="#lang.constants">vbFSSolid</a></li>
<li><a href="#lang.constants">vbFSTransparent</a></li>
<li><a href="#lang.constants">vbGet</a></li>
<li><a href="#ctrl.drawing">vbGrayCopy</a></li>
<li><a href="#lang.constants">vbGreen</a></li>
@ -1343,10 +1389,13 @@ img { max-width: 100%; }
<li><a href="#lang.constants">vbHimetric</a></li>
<li><a href="#ctrl.drawing">vbHimetric</a></li>
<li><a href="#ctrl.drawing">vbHorizontal</a></li>
<li><a href="#lang.constants">vbHorizontalLine</a></li>
<li><a href="#lang.screenobj">vbHourglass</a></li>
<li><a href="#lang.constants">vbInches</a></li>
<li><a href="#lang.constants">vbInformation</a></li>
<li><a href="#lang.constants">vbInsideSolid</a></li>
<li><a href="#lang.constants">vbInteger</a></li>
<li><a href="#lang.constants">vbInvisible</a></li>
<li><a href="#lang.clipboard">vbKeyBack</a></li>
<li><a href="#lang.clipboard">vbKeyDelete</a></li>
<li><a href="#lang.clipboard">vbKeyReturn</a></li>
@ -1381,6 +1430,10 @@ img { max-width: 100%; }
<li><a href="#lang.constants">vbPicTypeNone</a></li>
<li><a href="#lang.constants">vbPixels</a></li>
<li><a href="#lang.constants">vbPoints</a></li>
<li><a href="#lang.printerobj">vbPRCMColor</a></li>
<li><a href="#lang.printerobj">vbPRCMMonochrome</a></li>
<li><a href="#lang.printerobj">vbPRORLandscape</a></li>
<li><a href="#lang.printerobj">vbPRORPortrait</a></li>
<li><a href="#lang.constants">vbQuestion</a></li>
<li><a href="#lang.constants">vbReadOnly</a></li>
<li><a href="#lang.constants">vbRed</a></li>
@ -1395,6 +1448,7 @@ img { max-width: 100%; }
<li><a href="#ctrl.common.props">vbSizeNS</a></li>
<li><a href="#ctrl.common.props">vbSizeNWSE</a></li>
<li><a href="#ctrl.common.props">vbSizeWE</a></li>
<li><a href="#lang.constants">vbSolid</a></li>
<li><a href="#ctrl.drawing">vbSrcCopy</a></li>
<li><a href="#lang.constants">vbString</a></li>
<li><a href="#lang.constants">vbSunday</a></li>
@ -1414,6 +1468,7 @@ img { max-width: 100%; }
<li><a href="#ctrl.drawing">vbTransparentCopy</a></li>
<li><a href="#lang.constants">vbTuesday</a></li>
<li><a href="#lang.constants">vbTwips</a></li>
<li><a href="#lang.constants">vbUpwardDiagonal</a></li>
<li><a href="#lang.constants">vbUseCompareOption</a></li>
<li><a href="#lang.constants">vbUser</a></li>
<li><a href="#lang.constants">vbUserDefinedType</a></li>
@ -1421,6 +1476,7 @@ img { max-width: 100%; }
<li><a href="#lang.constants">vbUseSystemDayOfWeek</a></li>
<li><a href="#lang.constants">vbVariant</a></li>
<li><a href="#ctrl.drawing">vbVertical</a></li>
<li><a href="#lang.constants">vbVerticalLine</a></li>
<li><a href="#lang.constants">vbWednesday</a></li>
<li><a href="#lang.constants">vbWhite</a></li>
<li><a href="#lang.constants">vbYellow</a></li>
@ -1435,6 +1491,7 @@ img { max-width: 100%; }
<li><a href="#ctrl.terminal">VT100</a></li>
<li><a href="#ide.debug.watch">Watch Expressions</a></li>
<li><a href="#ide.debug.watch">Watch Window</a></li>
<li><a href="#lang.runtime">Wavetable synthesizer</a></li>
<li><a href="#lang.runtime">Web requests</a></li>
<li><a href="#lang.func.date">WEEKDAY</a></li>
<li><a href="#lang.func.date">WEEKDAYNAME</a></li>
@ -1457,6 +1514,10 @@ img { max-width: 100%; }
<li><a href="#ctrl.wrapbox">WrapBox</a></li>
<li><a href="#lang.fileio">WRITE #</a></li>
<li><a href="#lang.usercontrol">Writing a control</a></li>
<li><a href="#lang.runtime">WtAlloc</a></li>
<li><a href="#lang.runtime">WtInfo$</a></li>
<li><a href="#lang.runtime">WtStart</a></li>
<li><a href="#lang.runtime">WtUpload</a></li>
<li><a href="#ide.designer">WYSIWYG</a></li>
<li><a href="#lang.runtime">xfer.bas</a></li>
<li><a href="#lang.runtime">XferAnswer</a></li>
@ -3653,6 +3714,17 @@ Loop While INKEY$ = &quot;&quot;
FULLSCREEN
Do
Loop While INKEY$ = &quot;&quot;</code></pre>
<h2>Writing a Screen Saver</h2>
<p>A screen saver is a program with no form that shows its screen on the whole screen and draws until DVX closes it. Put the program (.app) in the SAVERS folder of your user folder (FileOpsKindDir$(FILEOPS_KIND_SAVERS, True)); it is then listed on Control Panel's Desktop page by its project Name. DVX starts it with the command line /S after the wait with no input, and closes its screen at the next key or mouse movement, which ends the program, so it needs no INKEY$ of its own.</p>
<pre><code>SCREEN 13
CLS
FULLSCREEN ON
DO
' draw a frame
FRAMEWAIT 30
LOOP</code></pre>
<p>SysScreenSaver$, SysSetScreenSaver, SysScreenSaverStart, and SysIdleSeconds (system.bas) read and change the screen saver from a program.</p>
</div>
<div class="topic" id="lang.fileio">
<h1>File I/O</h1>
@ -4681,6 +4753,62 @@ Print &quot;Running from: &quot; &amp; App.Path</code></pre>
If Clipboard.GetFormat(vbCFText) Then Text2.Text = Clipboard.GetText()</code></pre>
<p>A control or form of your own named Clipboard takes the name's place.</p>
</div>
<div class="topic" id="lang.printerobj">
<h1>Printer Object</h1>
<p>The Printer object draws pages on the printer chosen in the Control Panel, as in Visual Basic: text in any font at a size in points, lines, boxes, circles, dots, and pictures, anywhere on the page, page after page. It needs a printer model that prints pictures (the Control Panel's Printer page); on a color printer the colors print as they are, on the others in shades of grey.</p>
<p>On a PostScript printer the page is drawn by the printer itself, as lines, curves, and letters rather than dots, so it prints as sharp as the printer can. Text is in the printer's own Helvetica, Times, or Courier, whichever is nearest FontName: Courier for a fixed-pitch font or a name with Mono or Courier in it, Times for a name with Serif, Times, Roman, Tinos, or Ledger in it (but not Sans), and Helvetica for the rest. TextWidth and TextHeight measure the printer's letters, so text lines up as it will print.</p>
<p>A page is 8 by 10 inches. Its coordinates are twips (1440 an inch) until ScaleMode or Scale changes them, as on Visual Basic's Printer, so a program can place things in inches, centimetres, points, or its own units. Drawing goes to the page being made; NewPage prints it and starts the next, and EndDoc prints the last one and ends the document. The document starts when the first page is printed, at the printer and with the copies the program's last PrintChoose (print.bas) chose, or else as the Control Panel has them; while it prints, the Printing window shows, with Cancel. A program that ends with a page drawn or a document started has EndDoc done for it.</p>
<pre> Method Description
------ -----------
Printer.Print items Text at CurrentX / CurrentY in the font and ForeColor, as PRINT lays it out: ; joins, a comma goes to the next 14-character zone, TAB(n) and SPC(n) count characters of the font (its 0's width), and a new line goes down a line of the font. CurrentX / CurrentY move past it.
Printer.Line [(x1, y1)]-(x2, y2) [, color] [, B | BF] A line, a box, or a filled box, as on a PictureBox (STEP works too).
Printer.Circle (x, y), r [, color [, start, end [, aspect]]] A circle, ellipse, or arc; filled in FillColor when FillStyle is not transparent. Circles are round on paper on every printer.
Printer.PSet (x, y) [, color] One dot (DrawWidth across).
Printer.PaintPicture pic, x, y [, w, h [, srcX, srcY, srcW, srcH]] A picture (a PictureBox, a file, or LoadPicture's), stretched to w x h; without them, at its size on the screen (15 twips a pixel).
Printer.NewPage Print the page (even a blank one) and start the next; Page goes up by 1.
Printer.EndDoc Print the page drawn and end the document; Page goes back to 1.
Printer.KillDoc Throw the page drawn away and end the document (pages already printed stay printed).
Printer.TextWidth(text), TextHeight(text) The size text takes in the font, in the Printer's scale.
Printer.Scale (x1, y1)-(x2, y2), ScaleX, ScaleY As on a PictureBox: a scale of your own, and lengths from one scale to another.</pre>
<pre> Property Description
-------- -----------
CurrentX, CurrentY Where the next drawing starts.
ForeColor, FillColor, FillStyle, DrawWidth, DrawStyle As on a PictureBox (black, transparent fills, a solid pen 1 dot wide to start).
ScaleMode, ScaleLeft, ScaleTop, ScaleWidth, ScaleHeight The scale (vbTwips to start).
FontName, FontSize, FontBold, FontItalic, FontUnderline, FontStrikethru The font of Print's text; FontSize is in points (12 to start, in DejaVu Sans). Text prints crisp where the font has large sizes (the Printer Fonts add-on gives DejaVu Sans, Serif, and Sans Mono them), and blockier where a screen size is enlarged.
Copies How many times each page prints (1 to 99); as PrintChoose chose when it is not set.
Page The page being drawn (1 first). Read only.
Width, Height The page's size in twips (11520 by 14400). Read only.
TwipsPerPixelX, TwipsPerPixelY Twips in one of the printer's dots. Read only.
ColorMode vbPRCMColor on a color printer, else vbPRCMMonochrome. Read only.
Orientation vbPRORPortrait: pages print upright only.
DeviceName, Port The printer model and where it is connected, as the Control Panel names them. Read only.</pre>
<pre><code>Sub mnuReport_Click ()
Printer.ScaleMode = vbInches
Printer.FontSize = 18
Printer.FontBold = True
Printer.CurrentX = 1
Printer.CurrentY = 1
Printer.Print &quot;Sales by Region&quot;
Printer.FontSize = 11
Printer.FontBold = False
Printer.Line (1, 1.5)-(7, 1.5)
Printer.FillStyle = 0
Printer.FillColor = vbBlue
Printer.Line (1, 2)-(1 + nNorth / 100, 2.4), vbBlue, B
Printer.CurrentX = 1: Printer.CurrentY = 2.5
Printer.Print &quot;North&quot;; Tab(20); nNorth
Printer.EndDoc
End Sub</code></pre>
<p>The Printer has no Cls, Point, PAINT, or DRAW (Visual Basic's Printer has none of them either), and no Printer.Font object: use FontName, FontSize, and the other Font properties. A raster operation given to PaintPicture is not used on paper. A control or form of your own named Printer takes the name's place.</p>
<h2>Printer Constants</h2>
<pre> Constant Value Description
-------- ----- -----------
vbPRORPortrait 1 Printer.Orientation: upright pages (the only one)
vbPRORLandscape 2 Printer.Orientation: sideways pages (not supported)
vbPRCMMonochrome 1 Printer.ColorMode: black (and grey) only
vbPRCMColor 2 Printer.ColorMode: color</pre>
</div>
<div class="topic" id="lang.screenobj">
<h1>Screen Object</h1>
<p>The Screen object is the DVX desktop, as in Visual Basic: its size, so a program can place its forms (for example in a corner of the screen), its colour depth, the mouse pointer, and the arrangement of the windows on it.</p>
@ -4894,6 +5022,25 @@ End Sub</code></pre>
vbHimetric 8 Hundredths of a millimetre (ScaleX / ScaleY only; a Picture's Width and Height)
vbPicTypeNone 0 Picture.Type of an empty picture
vbPicTypeBitmap 1 Picture.Type of a loaded picture</pre>
<h2>Fill and Pen Constants</h2>
<p>The values of FillStyle and DrawStyle on Forms, PictureBoxes, and the Printer (see Drawing on Forms and PictureBoxes).</p>
<pre> Constant Value Description
-------- ----- -----------
vbFSSolid 0 FillStyle: filled solid in FillColor
vbFSTransparent 1 FillStyle: not filled (the default)
vbHorizontalLine 2 FillStyle: horizontal lines
vbVerticalLine 3 FillStyle: vertical lines
vbUpwardDiagonal 4 FillStyle: lines rising to the right
vbDownwardDiagonal 5 FillStyle: lines falling to the right
vbCross 6 FillStyle: a cross hatch
vbDiagonalCross 7 FillStyle: a diagonal cross hatch
vbSolid 0 DrawStyle: a solid pen (the default)
vbDash 1 DrawStyle: dashes
vbDot 2 DrawStyle: dots
vbDashDot 3 DrawStyle: dash, dot
vbDashDotDot 4 DrawStyle: dash, dot, dot
vbInvisible 5 DrawStyle: no lines or outlines (fills still drawn)
vbInsideSolid 6 DrawStyle: solid</pre>
<h2>VarType Constants</h2>
<p>The values VARTYPE returns (see Variants). For an array, VARTYPE adds vbArray to the type of its elements.</p>
<pre> Constant Value Kind of value
@ -4957,8 +5104,8 @@ End Sub</code></pre>
security.bas Security: random bytes for keys, a key exchange, a cipher, SHA-256 hashes, HMAC signatures, key making, and a safe compare (SecRandom$, SecDhCreate, SecCipherCrypt$, SecSha256$, SecHmac$, SecHkdf$, ...)
game.bas Games: whether a key is being held down right now, forgetting held keys, frames FRAMEWAIT skipped, waiting for the screen's retrace (GameKeyDown, GameKeyClear, FrameMissed, GameWaitRetrace)
joystick.bas Joysticks: how many there are, their names, where each stick points, and which buttons are pressed (JoyCount, JoyX, JoyY, JoyButton, ...); setting them up: calibration, dead zone, game port mode, keyboard joystick keys (JoySetCalibration, JoyCalibration, JoyRescan, JoyKeyIndex, JoySettingsStore, ...)
sound.bas Sound: play WAV and VOC files, tones and noise, set the volume (PlayWave, PlayTone, StopWave, SoundInfo$, ...); sounds loaded once and played with volume, pan, and pitch, sound made by the program as it goes, the FM synthesizer chip (SoundLoad, SoundPlay, SoundSetPitch, SoundCreate, SoundStreamOpen, SoundStreamWrite, FmAlloc, FmWrite, ...); DVX's own event sounds (SoundPlayEvent), master volume, sound driver, and MIDI settings (SoundEventFile$, SoundSetMasterVolume, SoundSettingsStore, ...)
music.bas Music: play MOD, S3M, XM, IT, and MIDI files, and play notes yourself (MusicLoad, MusicPlay, MusicStop, MusicNoteOn, MusicInfo$, ...); raw bytes to the MIDI port (MidiAcquire, MidiPut, MidiRelease, MidiPortInfo$)
sound.bas Sound: play WAV and VOC files, tones and noise, set the volume (PlayWave, PlayTone, StopWave, SoundInfo$, ...); sounds loaded once and played with volume, pan, and pitch, sound made by the program as it goes, recording from a microphone or line input (RecordStart, RecordStop, RecordLevel, ...), the FM synthesizer chip, a wavetable card's voices and memory (SoundLoad, SoundPlay, SoundSetPitch, SoundCreate, SoundStreamOpen, SoundStreamWrite, FmAlloc, FmWrite, WtAlloc, WtStart, ...); DVX's own event sounds (SoundPlayEvent), master volume, sound driver, and MIDI settings (SoundEventFile$, SoundSetMasterVolume, SoundSettingsStore, ...)
music.bas Music: play MOD, S3M, XM, IT, MIDI, WAV, and VOC files, and play notes yourself (MusicLoad, MusicPlay, MusicStop, MusicNoteOn, MusicInfo$, ...); instruments from banks and SoundFonts, a sound card's own (MusicSetBank, MusicPatchSet$, MusicRomBank$); raw bytes to the MIDI port (MidiAcquire, MidiPut, MidiRelease, MidiPortInfo$); what a MIDI keyboard plays, heard as it comes and recorded into MIDI files (MidiInOpen, MidiInMessage, MusicMidiSend, MidiRecordNew, MidiRecordSave, ...)
fileops.bas Files and folders: folder listings for a file list, paths and names, the file dialogs' filter rule, attributes and the time a file was changed, sizes, free space and disk sizes, drive kinds, whether a folder can be written, the folder for scratch files, making a folder path, and copying, moving, and deleting whole folders at once or as a job with progress, Cancel, and questions (FileOpsList, FileOpsListRows$, FileOpsFilterMatch, FileOpsSetModified, FileOpsDriveType, FileOpsIsWritable, FileOpsMakePath, FileOpsJobCreate, FileOpsJobRunFor, ...)
system.bas What Control Panel changes, at once for the whole desktop: the screen mode, the system colors and themes, the wallpaper, text smoothing, and the mouse (with DVX's limits and defaults, MOUSE_* and SYS_VIDEO_DEFAULT_*), and storing them in DVX's settings; the system font's character pictures; the mouse pointer and the Shift, Ctrl, and Alt keys anywhere on the screen, moving the pointer, typing keys into the window in front, a picture of the whole screen, and the memory (SysSetVideoMode, SysSetColor, SysLoadTheme, SysSetWallpaper, SysSetTextSmoothing, SysSetMouse, SysColorsStore, SysFontGlyphRow, SysMouseX, SysSendKey, SysScreenshot, SysMemoryFreeKb, ...)
font.bas Fonts: the font families DVX has, the sizes each comes in, whether one is fixed-pitch, and how wide text and how tall a line is in a font (FontFamilyCount, FontFamilyName$, FontFamilyFixed, FontSizeCount, FontSizeAt, FontNearestSize, FontTextWidth, FontLineHeight, FontAscent, FontRescan)
@ -4967,7 +5114,7 @@ End Sub</code></pre>
compiler.bas The BASIC compiler: compile a project or files you give it, find compile errors in their files, list a program's procedures and the language's keywords, build an .app or a control file; put a project's UserControls on a form designer's toolbox; read source text as the compiler does (tokens, code or string or comment, renaming a control in code, WithEvents variables, class Events), F1 help topics; open, change, and save project files and UserControl headers (CompSourceFromProject, CompSourceAdd, CompCompile, CompError$, CompMapFile$, CompProcList$, CompBuildApp, CompDesignControls, CompTokens$, CompRenameInCode$, CompHelpTopic$, ProjOpen, ProjSave, ProjCtlSetHeader$, ...)
debug.bas Run a compiled program inside yours and debug it: breakpoints, stepping, its variables, expressions, Immediate-window lines, its PRINT output (RunCreate, RunStart, RunPoll, DbgSetBreakpoints, DbgStepOver, DbgLocals$, DbgEval$, DbgExec$, ...)
designer.bas Form designers: the control types, whether each holds other controls and can be placed, the names of new controls, default events, toolbox tooltips and icons, and each type's properties (with their types and value names), methods, and events (with each event's parameters); the names in .frm and class module text; .frm files as data to read, edit, and write, controls copied and pasted as text, and a loaded form written back as .frm text (CtlTypeCount, CtlTypeName$, CtlTypeFlags, CtlPropCount, CtlPropName$, CtlPropType, CtlEventList$, CtlEventParams$, CtlTypeEventParams$, FrmFormName$, FrmControlNames$, ClsClassName$, FrmOpen, FrmText$, FrmCtlAdd, FrmCtlText$, FrmCtlPaste, FrmMenuAdd, FormText$, ...)
shell.bas DVX itself, everything Program Manager and Task Manager do: start programs and open documents, command lines (split into their parts) and the Run dialog, the installed programs and their names, file types, the running programs (find one, bring it to the front, ask it to close, or end it), this program's priority, keys that work in every program, Task Manager, system information, Exit DVX, the desktop and the program started after it, the DVX log; Program Manager's program groups with their items, shortcut keys, and icons (ShellRun, ShellRunProgram, ShellProgramScan, ShellAssocCount, ShellRunningId, ShellRunningActivate, ShellRunningClose, ShellArg$, ShellSetPriority, HotkeyAdd, ShellExitDvx, ShellGroupsLoad, ShellItemGet$, ShellItemIcon$, ...)
shell.bas DVX itself, everything Program Manager and Task Manager do: start programs (DVX's and DOS programs) and open documents, command lines (split into their parts) and the Run dialog, the installed programs and their names, file types, the running programs (find one, bring it to the front, ask it to close, or end it), this program's priority, keys that work in every program, Task Manager, system information, Exit DVX, the desktop and the program started after it, the DVX log; Program Manager's program groups with their items, shortcut keys, and icons (ShellRun, ShellRunProgram, ShellRunDos, ShellProgramScan, ShellAssocCount, ShellRunningId, ShellRunningActivate, ShellRunningClose, ShellArg$, ShellSetPriority, HotkeyAdd, ShellExitDvx, ShellGroupsLoad, ShellItemGet$, ShellItemIcon$, ...)
pkg.bas Add-on packages: the packages installed in DVX and their details, files, and needs; reading .DPK files and planning what installing them takes; installing and removing as a job with progress; trusting a publisher's key; and making packages, signing them, and making keys (PkgOpen, PkgInstalledRows$, PkgOfferFile, PkgPlan, PkgInstallStart, PkgRunFor, PkgRemoveStart, PkgBuild, PkgSign, PkgKeygen, ...)
json.bas JSON: read a document (a web service's reply, a settings file) and find values in it by path such as packages[3].version, and quote text for JSON of your own (JsonParse, JsonText$, JsonNumber, JsonCount, JsonKey$, JsonQuote$, ...)
http.bas Web requests: GET a page, a file, or a web service's answer, or POST to one, over the network a little at a time with progress, to memory or to a file (resuming one left part-way), following redirects (HttpOpen, HttpStart, HttpRunFor, HttpStatus, HttpBody$, HttpSaveTo, ...)
@ -5079,7 +5226,7 @@ End Sub</code></pre>
SerGetRi(com) True while the other end rings.
SerLineErrors(com) Errors seen on received data, added up: SER_LINE_OVERRUN (data came faster than it was read), SER_LINE_PARITY, SER_LINE_FRAMING, SER_LINE_BREAK; 0 for none.</pre>
<h2>Printing</h2>
<p>With print.bas in the project, a program prints like the programs that come with DVX. PrintTextDialog shows the Print dialog (printer, copies, pages) and prints the text on pages laid out by the page setup: margins, a header, and a footer with the document name, date, and page number. PrintPageSetup shows the Page Setup dialog, which the user's choices are saved from for every program. PrintPictureDialog prints a picture file scaled to the page, on printer models that print pictures (PrintCanPrintPictures says whether the chosen one does). PrintText and PrintPicture print without asking first. Each returns True when it printed.</p>
<p>With print.bas in the project, a program prints like the programs that come with DVX. PrintTextDialog shows the Print dialog (printer, copies, pages) and prints the text on pages laid out by the page setup: margins, a header, and a footer with the document name, date, and page number. PrintPageSetup shows the Page Setup dialog, which the user's choices are saved from for every program. PrintPictureDialog prints a picture file scaled to the page, on printer models that print pictures (PrintCanPrintPictures says whether the chosen one does), in color on a color printer (PrintCanPrintColor says whether it is one) and in shades of grey on the others. PrintText and PrintPicture print without asking first. Each returns True when it printed.</p>
<pre><code>Sub mnuPrint_Click ()
PrintTextDialog txtNotes.Text, &quot;Notes&quot;
End Sub
@ -5087,7 +5234,7 @@ End Sub
Sub mnuPageSetup_Click ()
PrintPageSetup
End Sub</code></pre>
<p>For printer output a line at a time, see LPRINT and OPEN &quot;LPT1:&quot;.</p>
<p>For printer output a line at a time, see LPRINT and OPEN &quot;LPT1:&quot;. To draw whole pages (text in any font and size, lines, boxes, circles, and pictures), use the Printer object.</p>
<p>A program that prints its own way has more:</p>
<pre> Function Description
-------- -----------
@ -5119,8 +5266,13 @@ End If</code></pre>
<pre> Function Description
-------- -----------
PrintModelCount() / PrintModelLabel$(model) How many printer models there are, and the name of each.
PrintDestCount() / PrintDestLabel$(dest) How many places the printer can be connected to (LPT1, LPT2, LPT3, a file), and the name of each.
PrintDestCount() / PrintDestLabel$(dest) How many places the printer can be connected to (LPT1 to LPT3, COM1 to COM4, a file), and the name of each.
PrintDestIsFile(dest) True for the destination that prints into a file.
PrintDestIsSerial(dest) True for a serial port (COM1 to COM4), which needs a speed and a handshake.
PrintBaudRate(index) The serial speeds offered, from index 0 (0 past the last).
PrintHandshakeCount() / PrintHandshakeLabel$(handshake) How many handshakes there are, and the name of each (None, XON / XOFF, Hardware (CTS), Hardware (DSR, Apple)).
PrintSettingBaud(prefs), PrintSettingHandshake(prefs) A serial printer's speed and handshake in the settings.
PrintSerialStore(prefs, baud, handshake) Put a serial printer's speed and handshake into the settings; False for a speed not offered.
PrintSettingModel(prefs) The printer model in the settings.
PrintSettingDest(prefs) Where the printer is connected.
PrintSettingFile$(prefs) The file printed into when the destination is a file.
@ -5148,7 +5300,7 @@ End Sub</code></pre>
<p>Paths: FileOpsPathNormalize$ (the full path of an existing folder, or &quot;&quot;), FileOpsPathParent$, FileOpsPathJoin$, FileOpsPathSame, FileOpsPathIsRoot, FileOpsPathIsAbsolute (True for a path that is complete by itself, such as &quot;C:\DOCS&quot;, False for one that counts from the current folder), FileOpsPathIsInside(path, folder) (True when path is folder itself or anywhere inside it: check it before copying or moving a folder, so it is never copied into itself), FileOpsPathSep$ (the character between folder names, &quot;\&quot; on DOS), FileOpsPathNative$ (a path written with that character, for showing it: &quot;C:/DOCS/A.TXT&quot; becomes &quot;C:\DOCS\A.TXT&quot;), FileOpsBaseName$, and FileOpsExtension$. Every one of them takes / and \ alike and gives back \. FileOpsFilterMatch(itemName, filter) tells whether a name matches a filter the way the file dialogs match it: wildcards * and ?, several patterns separated by ; such as &quot;*.bmp;*.png&quot;, case not mattering.</p>
<p>Files: FileOpsMakeDir and FileOpsRename (FileOpsError$ says why one failed), FileOpsTempPath$ and FileOpsReplaceFile (save safely: write the new file to FileOpsTempPath$(path$), then FileOpsReplaceFile swaps it in; the old file comes back if that fails), FileOpsValidName(folder, itemName) (whether a name can be used for a new file or folder in folder, by the rules of its disk; FileOpsError$ says why not), FileOpsValidLongName and FileOpsValidShortName (the long-name or the 8.3 rules by themselves, whatever the disk takes), FileOpsShortPath$ (the short 8.3 form of an existing path, for an old program that cannot take long names or blanks), FileOpsMakePath (a folder and every missing folder above it, which MKDIR does not make), FileOpsIsFolder, FileOpsGetAttr, and FileOpsSetAttr (the FILEOPS_ATTR_ bits), FileOpsModified$ and FileOpsSetModified (when a file was last changed, read and set in the form &quot;YYYY-MM-DD HH:MM&quot;; FileOpsSetModified returns False for a date that does not exist), FileOpsTreeSize with FileOpsTreeBytes, FileOpsTreeFiles, and FileOpsTreeFolders (the size of a whole folder), and FileOpsFormatSize$.</p>
<p>Drives: FileOpsDriveList$ (the drive letters), FileOpsDriveType (FILEOPS_DRIVE_FIXED for a hard disk, FILEOPS_DRIVE_REMOVABLE for a floppy disk drive, FILEOPS_DRIVE_REMOTE for a network drive or a CD-ROM; asking never makes a drive spin up), FileOpsBootDrive$ (the drive the computer started from), FileOpsFreeBytes, FileOpsFreeKb, and FileOpsTotalBytes (the size of the disk; right for disks past 2 GB too), FileOpsLongNames(path) (True when the disk holding path takes long file names: up to 255 characters, with spaces and several dots; otherwise names are 8.3). FileOpsIsWritable(folder) is False where files cannot be made (a CD-ROM, a write-protected floppy), and FileOpsReadOnlySystem() is True when nothing can be saved: DVX runs from such a disk and there is no TEMP folder to keep the user folder in. FileOpsTempDir$() is the folder for scratch files (&quot;&quot; when there is none).</p>
<p>DVX's folders: FileOpsUserDir$() is the user folder (USER in the DVX folder, or the folder DVXUSER names), where everything DVX and its programs save goes; FileOpsUserPath$(name) is a file or folder in it, for example FileOpsUserPath$(&quot;DOWNLOAD&quot;); FileOpsUserInTemp() is True when DVX runs from a disk it cannot write to and keeps the user folder in the TEMP folder. A program's own folder there is App.User. The fonts, sounds, themes, desktop pictures, and MIDI instrument banks come in two folders each, DVX's own (and add-on packages') in SHARED and the user's in the user folder; the kinds are FILEOPS_KIND_FONTS, FILEOPS_KIND_SOUNDS, FILEOPS_KIND_THEMES, FILEOPS_KIND_WPAPER, and FILEOPS_KIND_BANKS. An add-on's files are in a folder of its vendor's inside a kind's folder and are named VENDOR\NAME (for example ACME\SPACE.THM). FileOpsKindDir$(kind, user) is DVX's folder of a kind (user False) or the user's (True); FileOpsKindBrowseDir$(kind) is the one a file dialog starts in (the user's when it exists); FileOpsKindFind$(kind, fileName) finds a file by name, the user's first (&quot;&quot; when there is none); FileOpsKindName$(kind, path) is the name alone of a file in one of the two folders, the way settings store it (&quot;&quot; for any other path); FileOpsKindList(kind) lists both folders as one, sorted by name, a user's file hiding DVX's of the same name (a list for FileOpsListCount, FileOpsListName$, and the rest; FileOpsListFree when done). Programs read DVX's SHARED folder but never write in it.</p>
<p>DVX's folders: FileOpsUserDir$() is the user folder (USER in the DVX folder, or the folder DVXUSER names), where everything DVX and its programs save goes; FileOpsUserPath$(name) is a file or folder in it, for example FileOpsUserPath$(&quot;DOWNLOAD&quot;); FileOpsUserInTemp() is True when DVX runs from a disk it cannot write to and keeps the user folder in the TEMP folder. A program's own folder there is App.User. The fonts, sounds, themes, desktop pictures, MIDI instrument banks, and screen savers come in two folders each, DVX's own (and add-on packages') in SHARED and the user's in the user folder; the kinds are FILEOPS_KIND_FONTS, FILEOPS_KIND_SOUNDS, FILEOPS_KIND_THEMES, FILEOPS_KIND_WPAPER, FILEOPS_KIND_BANKS, and FILEOPS_KIND_SAVERS. An add-on's files are in a folder of its vendor's inside a kind's folder and are named VENDOR\NAME (for example ACME\SPACE.THM). FileOpsKindDir$(kind, user) is DVX's folder of a kind (user False) or the user's (True); FileOpsKindBrowseDir$(kind) is the one a file dialog starts in (the user's when it exists); FileOpsKindFind$(kind, fileName) finds a file by name, the user's first (&quot;&quot; when there is none); FileOpsKindName$(kind, path) is the name alone of a file in one of the two folders, the way settings store it (&quot;&quot; for any other path); FileOpsKindList(kind) lists both folders as one, sorted by name, a user's file hiding DVX's of the same name (a list for FileOpsListCount, FileOpsListName$, and the rest; FileOpsListFree when done). Programs read DVX's SHARED folder but never write in it.</p>
<p>FileOpsCopyTree, FileOpsMoveTree, and FileOpsDeleteTree do a whole folder at once. For a long copy, move, or delete the program stays usable when it runs the work as a job, a little at a time from a Timer: FileOpsJobCreate, then FileOpsJobAddSource for each file or folder, then FileOpsJobRunFor from the timer until it returns FILEOPS_STEP_DONE or FILEOPS_STEP_CANCELLED. When it returns FILEOPS_STEP_ASK (a file already exists, a file is read-only) or FILEOPS_STEP_ERROR, show FileOpsJobMessage$ and pass the user's choice to FileOpsJobAnswer. FileOpsJobCurrent$, FileOpsJobFilesDone, FileOpsJobFilesTotal, FileOpsJobPercent, FileOpsJobBytesDone, and FileOpsJobBytesTotal show the progress, and FileOpsJobCancel stops the job. Files copied from a CD-ROM are read-only; FileOpsJobClearAttr job, FILEOPS_ATTR_READONLY before the job runs makes every copy changeable (FILEOPS_ATTR_EDITABLE clears all four attribute bits). Whatever a program leaves open is freed when it ends.</p>
<pre><code>Dim job As Long
@ -5176,7 +5328,7 @@ Sub Timer1_Timer ()
End Sub</code></pre>
<h2>Working with DVX</h2>
<p>With shell.bas in the project, a program works with DVX the way Program Manager does -- a whole desktop can be written in BASIC.</p>
<p>Starting programs. ShellRun program, args starts a program (args is what it gets as COMMAND$), or opens a document in the program set for its type; it returns True when it started. ShellRunProgram(program, args, folder) does the same the way a Program Manager item does: file names in args, and a document named without a folder, are looked for in folder first (&quot;&quot; for none), and it returns the new program's id (0 when it did not start; DVX has already said why). ShellMinimizeApp id runs that program minimized: its windows become icons, including the ones it opens while it starts. ShellRunCommand(commandLine) runs a whole command line (a program, in double quotes when its name has a blank, then its arguments) and returns the id too. ShellRunDialog$(history) shows DVX's Run dialog offering history (earlier commands, newest first, one per line) and returns what the user chose, &quot;&quot; for Cancel. ShellOpenDocument path opens a document in the program set for its type in the Control Panel.</p>
<p>Starting programs. ShellRun program, args starts a program (args is what it gets as COMMAND$), runs a DOS program, or opens a document in the program set for its type; it returns True when it started (or the DOS program will run). ShellRunProgram(program, args, folder) does the same the way a Program Manager item does: file names in args, and a document named without a folder, are looked for in folder first (&quot;&quot; for none), and it returns the new program's id (SHELL_RUN_DOS for a DOS program, 0 when it did not start; DVX has already said why). DOS programs are .EXE, .COM, and .BAT files (ShellIsDosProgram(path) says whether a file is one). ShellRunDos program, args, folder, pause runs one with DVX stepped aside: once your procedure has returned, DVX names the programs running besides the desktop, this one included, and asks them to close (each asks about unsaved work; No, or a program kept open, cancels the run); the screen then becomes the DOS screen until the program ends, and DVX comes back with the desktop. folder is where it runs (&quot;&quot; for its own folder); pause True shows &quot;Press any key to return to DVX.&quot; when it ends. ShellMinimizeApp id runs that program minimized: its windows become icons, including the ones it opens while it starts. ShellRunCommand(commandLine) runs a whole command line (a program, in double quotes when its name has a blank, then its arguments) and returns the id too. ShellRunDialog$(history) shows DVX's Run dialog offering history (earlier commands, newest first, one per line) and returns what the user chose, &quot;&quot; for Cancel. ShellOpenDocument path opens a document in the program set for its type in the Control Panel.</p>
<p>Installed programs. ShellProgramScan(folder, skipPath) finds every program in folder and its subfolders (&quot;&quot; for the APPS folder) and returns a list: ShellProgramCount(list) programs, ShellProgramPath$(list, index) each one's path (index from 0), ShellProgramFree list when done (a list not freed is freed when the program ends). Give ShellAppPath$() as skipPath to leave this program out. ShellProgramName$(path) and ShellProgramDescription$(path) are the name and description a program shows, and ShellIsProgram(path) tells a program from a document. LOADPICTURE of a program gives its icon, so a PictureBox can show a grid of programs with PaintPicture. ShellProgramsFolder$() is the folder the installed programs are in (where ShellProgramScan(&quot;&quot;) looks), for example to start a Browse for a program there with DlgFileOpenIn$.</p>
<p>File types. ShellAssocProgram$(extension) tells which program opens files with that extension (with &quot;,arguments&quot; after it when it is given any), ShellAssocCommand$(document) just the program that opens a document. ShellAssocCount() file types are set; ShellAssocExt$(index) and ShellAssocValue$(index) read them (index from 0). ShellAssocSet(extension, program) sets one and ShellAssocRemove(extension) removes one, saved at once; ShellAssocNormalize$(extension) is the extension as stored (&quot;.txt&quot; gives &quot;TXT&quot;; &quot;&quot; when it cannot be one).</p>
<p>Running programs. ShellRunningCount() says how many programs are running, and ShellRunningId(index) is the id of each one (index from 0; the same id ShellRunProgram returns). ShellAppId() is this program's own id. ShellRunningName$(id) and ShellRunningPath$(id) are the name a running program shows and the path of its .app (&quot;&quot; when it is not running), and ShellRunningFind(program) is the id of a running copy of a program, 0 when it is not running. ShellRunningActivate id brings a program to the front the way Task Manager's Switch To does (a minimized window is restored). ShellRunningClose id asks a program to close as if the user had closed its windows: it may ask to save its work and the user may cancel, and it is asked once your code has returned to DVX, so check from a Timer whether it is still running. ShellRunningKill id ends a program at once without asking it, the way Task Manager's End Task does: whatever it had not saved is lost, so keep it for a program that does not respond. ShellAppIsHung(id) is True when a program has been busy for 5 seconds or longer (&quot;Not responding&quot; in Task Manager). A program cannot end itself with ShellRunningKill (END does that). ShellAppMemory(id) is how many bytes of memory a program is using. ShellChangeCount() changes whenever a program starts or ends: check it from a Timer and update what you show when it is not the value you saw last. ShellTaskManager opens the Task Manager, ShellSystemInfo$() describes the computer (several lines), and ShellExitDvx exits DVX: every program is asked to close, each asking about unsaved work, and a program that stays open stops the exit (ask the user first).</p>
@ -5235,7 +5387,7 @@ End Sub</code></pre>
End Sub</code></pre>
<h2>Add-on Packages</h2>
<p>With pkg.bas in the project, a program installs, removes, and makes add-on packages -- the .DPK files Software installs -- the way Software and Package Builder (both written in BASIC) do. PkgOpen() starts a session (a number; PkgClose ends it), and PkgError$(session) says why the last call that failed did. Lists come back as rows for a ListView's SetRows: cells separated by TAB, each row ending in a line feed.</p>
<p>What is installed. PkgInstalledRows$ lists every installed package (DVX itself is kpunch.dvx): id, name, version, kind, and summary. A package is named by its id, vendor.name (acme.chess). PkgField$(s, id, field) gives one detail (PKG_FIELD_NAME, PKG_FIELD_VERSION, PKG_FIELD_PUBLISHER, PKG_FIELD_SIGNER_NAME, ...); PkgFilesRows$, PkgDependsRows$, and PkgNeededBy$ its files, what it needs, and what needs it.</p>
<p>What is installed. PkgInstalledRows$ lists every installed package (DVX itself is kpunch.dvx): id, name, version, kind, and summary. A package is named by its id, vendor.name (acme.chess). PkgField$(s, id, field) gives one detail (PKG_FIELD_NAME, PKG_FIELD_VERSION, PKG_FIELD_PUBLISHER, PKG_FIELD_SIGNER_NAME, ...); PkgFilesRows$, PkgDependsRows$, and PkgNeededBy$ its files, what it needs, and what needs it. PkgFileOwner$(s, fileName) is the other way: the id of the package that put a file there (its name from the DVX folder, such as &quot;SHARED\BANKS\KPUNCH\DMXOPL.OP2&quot;; &quot;&quot; when none did).</p>
<p>Installing. PkgOfferFile(s, path) reads a package file and every package beside it (what it may need) as offers, numbered from 0, and returns the number of the one at path (-1 when it cannot be read). PkgOfferField$ and PkgOfferFilesRows$ describe an offer before it is installed; PKG_FIELD_TRUST says whether DVX trusts who signed it. PkgPlan(s, &quot;0&quot;) plans installing it with everything it needs, checked against this DVX and the packages installed (False, with PkgError$ saying why, when it cannot be installed); PkgPlanRows$ lists what will go in, PkgPlanBytes the disk space, and PkgPlanRestart whether libraries or widgets are among them (they work from the next time DVX starts). PkgInstallStart(s) then starts the job, and PkgRunFor(s, milliseconds) runs it a little at a time, returning PKG_RUN_BUSY until it is PKG_RUN_DONE or PKG_RUN_FAILED (PkgRunMessage$ says why); PkgRunPercent and PkgRunCurrent$ show how far it is.</p>
<pre><code>offer = PkgOfferFile(s, path)
If offer &gt;= 0 And PkgPlan(s, CStr(offer)) Then
@ -5289,12 +5441,13 @@ body = &quot;{&quot; &amp; JsonQuote$(&quot;name&quot;) &amp; &quot;: &quot; &am
<p>Screen mode: SysVideoModeCount() says how many modes the display offers (numbered from 0), and SysVideoModeWidth, SysVideoModeHeight, and SysVideoModeBpp (bits per pixel) describe each. SysSetVideoMode(wide, high, bpp) changes the mode and keeps every window; it returns False when the mode could not be set (the old one stays), also while a program has the whole screen to itself. A mode the monitor cannot show leaves the user unable to answer, so do as Control Panel does: ask &quot;Keep this mode?&quot; and go back to the old mode by itself after some seconds. Screen.Width, Screen.Height, and Screen.BitsPerPixel tell the mode in use, and SYS_VIDEO_DEFAULT_WIDTH, SYS_VIDEO_DEFAULT_HEIGHT, and SYS_VIDEO_DEFAULT_BPP the mode DVX starts in when its settings name none. SysScreenshot(path) saves the whole screen as a picture file (BMP when path ends in .bmp, PNG otherwise) and returns True when it was written.</p>
<p>Colors: the system colors are numbered from 0 to SysColorCount() - 1. SysColorLabel$(id) is the text to show for one (&quot;Desktop&quot;, &quot;Window Face&quot; ...), SysColorName$(id) the name it is stored as, and SysColorId(colorName) the id of a name (-1 for none) -- to draw in the user's colors, for example SysGetColor(SysColorId(&quot;desktop&quot;)). SysGetColor and SysSetColor read and set a color as an RGB() value; each SysSetColor redraws the whole screen. SysResetColors goes back to DVX's own colors. SysLoadTheme(path) and SysSaveTheme(path) read and write a theme file (.THM; DVX's own are in SHARED\THEMES, the user's in the THEMES folder of the user folder, FileOpsKindDir$(FILEOPS_KIND_THEMES, True)); both return True when they worked.</p>
<p>Wallpaper: SysSetWallpaper(path) shows a BMP, JPG, PNG, or GIF image behind the desktop (&quot;&quot; for none) and returns False when the image could not be loaded (the old one stays). SysSetWallpaperMode mode says how it fills the screen, a choice of PREFS_CHOICE_WALLPAPER (Stretch, Tile, or Center; see Settings Files). SysWallpaper$() and SysWallpaperMode() tell what is in use.</p>
<p>Screen saver: SysSetScreenSaver fileName, minutes chooses the screen saver -- a program in the SAVERS folders, named as FileOpsKindList(FILEOPS_KIND_SAVERS) lists it, or &quot;&quot; for none -- and the minutes with no key or mouse input before it starts (SCREEN_SAVER_WAIT_MIN to SCREEN_SAVER_WAIT_MAX; DVX's default is SCREEN_SAVER_WAIT_DEFAULT). SysScreenSaver$() and SysScreenSaverWait() tell what is in use, SysScreenSaverStart() starts it now as Control Panel's Test does (False when none is chosen or one is running), and SysScreenSaverRunning() is True while one runs. SysIdleSeconds() is how long it has been since the last key or mouse input anywhere on the screen.</p>
<p>Text: SysSetTextSmoothing True smooths the edges of text and SysSetTextSmoothing False stops it; SysTextSmoothing() tells which the user chose. Text is smoothed only when the screen shows more than 256 colors, and only in the fonts and sizes that come smoothed. Every window is drawn again when it changes.</p>
<p>Mouse: SysSetMouse wheelDir, dblClickMs, accel, mickeys, wheelStep applies a whole mouse setup at once: the scroll wheel's direction (1 or -1, the values of PREFS_CHOICE_WHEEL), the double-click time in milliseconds, the acceleration (a value of PREFS_CHOICE_ACCEL), how far the mouse moves for 8 pixels of pointer movement (8 is normal, higher is slower), and the lines scrolled per wheel notch (1 to 10). An accel or mickeys of 0 leaves that one as it is. SysMouseWheelDir, SysMouseDoubleClick, SysMouseAccel, SysMouseMickeys, and SysMouseWheelStep read the setup in effect. MOUSE_WHEEL_STEP_MIN and MOUSE_WHEEL_STEP_MAX are the limits of the wheel step, and MOUSE_WHEEL_STEP_DEFAULT, MOUSE_DBLCLICK_DEFAULT_MS, and MOUSE_SPEED_DEFAULT are DVX's defaults (what a Default button puts back).</p>
<p>The pointer and the keyboard: SysMouseX() and SysMouseY() are where the mouse pointer is on the screen, and SysMouseButtons() the buttons held (vbLeftButton, vbRightButton, and vbMiddleButton bits) -- also while the pointer is over another program's window, where your MouseMove events do not see it. SysSetMousePos x, y moves the pointer (it is kept on the screen). SysShiftState() is the Shift, Ctrl, and Alt keys held now (vbShiftMask, vbCtrlMask, and vbAltMask bits). SysSendKey(keyCode, shift) types a key into the window that has the focus as if the user pressed it, like SendKeys in other BASICs: keyCode as a KeyDown event gets it -- a character code such as ASC(&quot;a&quot;) or 13 for Enter, or a vbKey constant such as vbKeyF1 -- and shift the vbShiftMask, vbCtrlMask, and vbAltMask bits held with it (SysSendKey ASC(&quot;s&quot;), vbCtrlMask is Ctrl+S). The keys arrive in order, one at a time, once your code has returned to DVX; up to 64 can wait, and SysSendKey returns False when that many are waiting. A program cannot press the mouse buttons: to &quot;click&quot; a control, call its event procedure or set its value.</p>
<p>Memory: SysMemoryTotalKb() is the computer's memory in KB and SysMemoryFreeKb() how much of it is free (-1 when it cannot be told).</p>
<p>System font: SysFontWidth() and SysFontHeight() are the size of every character of the system font in pixels, and SysFontFirstChar() to SysFontFirstChar() + SysFontCharCount() - 1 the character codes it has. SysFontGlyphRow(code, row) is one row of a character's picture: a bit per pixel, &amp;H80 the leftmost -- for drawing text dot by dot, enlarged or in a font editor of your own.</p>
<p>Saving: SysColorsStore, SysWallpaperStore, SysFontsStore, and SysMouseStore write the colors, the wallpaper, text smoothing, and the mouse setup into a prefs.bas handle, in the sections DVX reads when it starts; PrefsSetVideoMode does the same for a screen mode. Store them in PrefsLoad(PrefsDvxIni$()) and save it, and DVX starts with them next time. SysColorsLoad, SysWallpaperLoad, SysFontsLoad, and SysMouseLoad apply what a handle holds. A PrefsCreate handle filled with the Store calls is a snapshot in memory: load it again to undo every change, the way Cancel works in Control Panel.</p>
<p>Saving: SysColorsStore, SysWallpaperStore, SysScreenSaverStore, SysFontsStore, and SysMouseStore write the colors, the wallpaper, the screen saver, text smoothing, and the mouse setup into a prefs.bas handle, in the sections DVX reads when it starts; PrefsSetVideoMode does the same for a screen mode. Store them in PrefsLoad(PrefsDvxIni$()) and save it, and DVX starts with them next time. SysColorsLoad, SysWallpaperLoad, SysScreenSaverLoad, SysFontsLoad, and SysMouseLoad apply what a handle holds. A PrefsCreate handle filled with the Store calls is a snapshot in memory: load it again to undo every change, the way Cancel works in Control Panel.</p>
<pre><code>Dim snap As Long
Dim oldW As Long, oldH As Long, oldBpp As Long
@ -5420,8 +5573,8 @@ Sub cmdFire_Click ()
End If
End Sub</code></pre>
<p>WAV files must be uncompressed (8 or 16 bits, mono or stereo); VOC files may be 8- or 16-bit. QBasic's BEEP, SOUND, and PLAY work too, without sound.bas.</p>
<p>PlayTriangle(frequency, milliseconds, volume) plays a triangle tone, softer than PlayTone's square tone. SoundGetVolume() gives the volume of everything the program plays. SoundCaps(field) tells what the sound device can do, by name in any case: &quot;dac&quot; (it plays recorded sound), &quot;synth&quot; (it has a music synthesizer), &quot;tone&quot; (it plays tones on a tone generator), and &quot;running&quot; are True or False; &quot;voices&quot; (how many sounds play at once), &quot;rate&quot; (hertz), &quot;bits&quot;, and &quot;channels&quot; are numbers. SoundPlayEvent eventIdx, wait plays one of DVX's own event sounds (SOUND_EVENT_DEFAULT, SOUND_EVENT_ERROR, SOUND_EVENT_WARNING, ...), the one the settings choose; with wait True it returns once the sound has played.</p>
<p>A sound played often is best loaded once. SoundLoad(fileName) loads a WAV or VOC file and returns a sound number, or 0 (SoundError$() says why); SoundCreate(data, rate, bits, channels) makes a sound from raw sound data in a string: 8-bit samples (0 to 255, 128 is silence) or 16-bit ones (two bytes each, the low byte first), mono or stereo (left, right, left, ...), rate times a second (SOUND_RATE_MIN to SOUND_RATE_MAX). SoundPlay(sound, volume, pan, loopIt) plays it on a new voice and returns the voice number; pan goes from SOUND_PAN_LEFT (-100) through SOUND_PAN_CENTER (0) to SOUND_PAN_RIGHT (100). SoundLength(sound) is its length in milliseconds and SoundFree sound stops its voices and forgets it. While a voice plays, SoundSetVolume voice, volume, SoundSetPan voice, pan, and SoundSetPitch voice, percent change it (pitch is a percent of the recorded speed: SOUND_PITCH_NORMAL is 100, 200 is an octave higher, from SOUND_PITCH_MIN 25 to SOUND_PITCH_MAX 400), and SoundSetFrequency voice, hertz changes a tone's frequency. A program's sounds are freed when it ends.</p>
<p>PlayTriangle(frequency, milliseconds, volume) plays a triangle tone, softer than PlayTone's square tone. SoundGetVolume() gives the volume of everything the program plays. SoundCaps(field) tells what the sound device can do, by name in any case: &quot;dac&quot; (it plays recorded sound), &quot;synth&quot; (it has a music synthesizer), &quot;tone&quot; (it plays tones on a tone generator), &quot;running&quot;, and &quot;record&quot; (it records sound) are True or False; &quot;voices&quot; (how many sounds play at once), &quot;rate&quot; (hertz), &quot;bits&quot;, &quot;channels&quot;, and &quot;recordsources&quot; (the inputs it records from) are numbers. SoundPlayEvent eventIdx, wait plays one of DVX's own event sounds (SOUND_EVENT_DEFAULT, SOUND_EVENT_ERROR, SOUND_EVENT_WARNING, ...), the one the settings choose; with wait True it returns once the sound has played.</p>
<p>A sound played often is best loaded once. SoundLoad(fileName) loads a WAV or VOC file and returns a sound number, or 0 (SoundError$() says why); SoundCreate(data, rate, bits, channels) makes a sound from raw sound data in a string: 8-bit samples (0 to 255, 128 is silence) or 16-bit ones (two bytes each, the low byte first), mono or stereo (left, right, left, ...), rate times a second (SOUND_RATE_MIN to SOUND_RATE_MAX). SoundPlay(sound, volume, pan, loopIt) plays it on a new voice and returns the voice number; pan goes from SOUND_PAN_LEFT (-100) through SOUND_PAN_CENTER (0) to SOUND_PAN_RIGHT (100). SoundLength(sound) is its length in milliseconds and SoundFree sound stops its voices and forgets it. While a voice plays, SoundSetVolume voice, volume, SoundSetPan voice, pan, and SoundSetPitch voice, percent change it (pitch is a percent of the recorded speed: SOUND_PITCH_NORMAL is 100, 200 is an octave higher, from SOUND_PITCH_MIN 25 to SOUND_PITCH_MAX 400), and SoundSetFrequency voice, hertz changes a tone's frequency. SoundPause voice holds a sound's voice where it is, silent, and SoundResume voice goes on from there (a tone cannot be paused). A program's sounds are freed when it ends.</p>
<pre><code>Dim Shared laser As Long
Sub Form1_Load ()
@ -5433,15 +5586,21 @@ Sub Fire (x As Integer)
v = SoundPlay(laser, 80, (x - 160) * 100 \ 160, False)
SoundSetPitch v, 90 + Int(Rnd * 20)
End Sub</code></pre>
<p>A program can also make its sound as it goes, for speech or music of its own. SoundStreamOpen(rate, bits, channels, bufferMs) opens a stream that starts playing at once (silence until data arrives) and holds bufferMs milliseconds of sound (0 for the usual SOUND_STREAM_MS_DEFAULT; SOUND_STREAM_MS_MIN to SOUND_STREAM_MS_MAX). SoundStreamWrite(stream, data) adds raw sound data in the stream's format and returns how many bytes it took; keep the rest and write it again later. SoundStreamSpace(stream) is the room left and SoundStreamQueued(stream) what is waiting to play, both in samples (a stereo sample counts once). SoundStreamVoice(stream) is the stream's voice, for SoundSetVolume, SoundSetPan, and SoundSetPitch, and SoundStreamClose stream stops it. A Timer keeps a stream fed:</p>
<p>A program can also make its sound as it goes, for speech or music of its own. SoundStreamOpen(rate, bits, channels, bufferMs) opens a stream that starts playing at once (silence until data arrives) and holds bufferMs milliseconds of sound (0 for the usual SOUND_STREAM_MS_DEFAULT; SOUND_STREAM_MS_MIN to SOUND_STREAM_MS_MAX). SoundStreamWrite(stream, data) adds raw sound data in the stream's format and returns how many bytes it took; keep the rest and write it again later. SoundStreamSpace(stream) is the room left and SoundStreamQueued(stream) what is waiting to play, both in samples (a stereo sample counts once). SoundStreamVoice(stream) is the stream's voice, for SoundSetVolume, SoundSetPan, SoundSetPitch, SoundPause, and SoundResume. SoundStreamFlush stream drops what is waiting to play, so what is written next is heard at once (to jump to another place in what you play), and SoundStreamClose stream stops it. A Timer keeps a stream fed:</p>
<pre><code>Sub Timer1_Timer ()
Dim taken As Long
taken = SoundStreamWrite(stream, pending)
pending = Mid$(pending, taken + 1)
If Len(pending) = 0 Then pending = MakeMoreSound()
End Sub</code></pre>
<p>A program can record sound from the sound card's microphone, line, or CD input into a WAV file. SoundCaps(&quot;record&quot;) says whether the card can, and SoundCaps(&quot;recordsources&quot;) which inputs it has (the bit 2 ^ RECORD_MIC, RECORD_LINE, or RECORD_CD set for each). RecordStart(fileName, rate, bits, channels, inputSource) starts recording (0 for 22,050 Hz, 16-bit, mono) and returns True, or False with SoundError$ saying why; the card records at its nearest, which RecordRate(), RecordBits(), and RecordChannels() tell. While it records, RecordLength() is how long the recording is (milliseconds) and RecordLevel() the loudest sound since it was last asked (percent: a level meter); RecordLost() counts samples dropped because DVX was too busy. RecordStop() ends it and returns True when the file was all written; Recording() is True in between. Most sound cards record or play, not both, so nothing plays while a program records, and one program records at a time. A program's recording ends when the program does.</p>
<pre><code>If RecordStart(&quot;NOTE.WAV&quot;, 0, 0, 0, RECORD_MIC) Then
' ... a Timer shows RecordLength() and RecordLevel()
ok = RecordStop()
End If</code></pre>
<p>On a computer with an FM synthesizer chip (AdLib and most Sound Blasters), a program can play instruments of its own. FmInfo$(field) describes the chip: &quot;description&quot; (like &quot;OPL3 FM synthesizer at 388h&quot;, &quot;&quot; when there is none), &quot;voices&quot;, &quot;free&quot; (voices no program has), &quot;stereo&quot;, and &quot;owned&quot; (one program has the whole chip). FmAlloc() takes one of its two-operator voices (0 when none is free), FmWrite(voice, register, value) sets one of the voice's registers (the FM_ constants: FM_MOD_CHAR, FM_CAR_LEVEL, FM_FNUM_LOW, FM_KEY_BLOCK with FM_KEY_ON, ...; True when it worked), and FmFree voice gives it back. A player of chip music files can take the whole chip with FmRawAcquire() (False while another program has it), set any register with FmRawWrite(register, value) (bank * FM_BANK_REGS + register; the second bank only on an OPL3) and give it back with FmRawRelease. A frequency number for FM_FNUM_LOW and FM_KEY_BLOCK is hertz * 2 ^ 20 / (FM_CHIP_HZ * 2 ^ block).</p>
<p>sound.bas also changes DVX's own sound settings, as the Control Panel's Sounds page does. DVX plays a sound for each of SoundEventCount() events, numbered from 0: SoundEventLabel$(eventIdx) names one (&quot;Start DVX&quot;, &quot;Error&quot;, ...) and SoundEventKey$(eventIdx) gives its key in DVX.INI. With a settings handle from prefs.bas (PrefsLoad(PrefsDvxIni$())), SoundEventFile$(handle, eventIdx) is the event's sound file (&quot;&quot; for none) and SoundSetEventFile handle, eventIdx, fileName changes it; after the program saves the file, SoundEventsReload makes DVX play the new sounds. SoundTestFile(fileName) plays a file the way DVX plays its event sounds (0 when it cannot, and SoundError$() says why), and SoundFolder$() is the folder of DVX's own sounds. SoundMasterVolume() and SoundSetMasterVolume percent are the volume of all sound from every program. SoundDriverCount() reads the list of sound drivers and SoundDriverName$(index) names each; SoundDriverAuto$() is the setting that means &quot;find the best one&quot;. SoundMidiCount() and SoundMidiLabel$(index) list where MIDI music can play. SoundSettingDriver$(handle), SoundSettingMidi(handle), and SoundSettingVolume(handle) read the sound driver, MIDI choice, and master volume from the settings, and SoundSettingsStore handle, driver, midi, volume stores them (a new driver or MIDI choice takes effect when DVX next starts).</p>
<p>On a wavetable sound card (a Gravis UltraSound, a Sound Blaster AWE32 or AWE64), a program can play recorded sounds on the card's own voices from the card's memory. WtInfo$(field) describes the card: &quot;description&quot; (&quot;&quot; when there is none), &quot;voices&quot;, &quot;free&quot; (voices no program has), &quot;memory&quot; and &quot;freememory&quot; (bytes), &quot;level&quot; (how many centibels louder a voice at full volume is than the loudest recorded sound the card plays: 0 when it is the same or not known), and what the card does itself (&quot;envelopes&quot;, &quot;lfos&quot;, &quot;filter&quot;, &quot;effects&quot;, &quot;8bit&quot;, &quot;rom&quot;; True or False as text). WtMemAlloc(bytes, bits) takes memory for samples of 8 or 16 bits (its address, -1 when there is no room), WtUpload(address, pcm, bits) copies 16-bit mono samples there (a binary string, two bytes a sample; True when it worked), and WtMemFree address gives it back. WtAlloc() takes a voice (0 when none is free); WtStart(voice, address, startFrame, endFrame, loopStart, loopEnd, loopMode, bits, pitch, attenuation, pan) plays a sample on it from startFrame (0: its first; loopMode 0 plays once, 1 loops, 3 loops until WtRelease; pitch in cents, 0 for 44,100 samples a second and 1200 an octave higher; attenuation in centibels, 0 loudest and 60 half as loud; pan -100 to 100). WtSetPitch, WtSetAttenuation, and WtSetPan change a playing voice, WtStop silences it, WtActive(voice) is True while it sounds, and WtFree voice gives it back. Everything a program took is given back when it ends.</p>
<p>sound.bas also changes DVX's own sound settings, as the Control Panel's Sounds page does. DVX plays a sound for each of SoundEventCount() events, numbered from 0: SoundEventLabel$(eventIdx) names one (&quot;Start DVX&quot;, &quot;Error&quot;, ...) and SoundEventKey$(eventIdx) gives its key in DVX.INI. With a settings handle from prefs.bas (PrefsLoad(PrefsDvxIni$())), SoundEventFile$(handle, eventIdx) is the event's sound file (&quot;&quot; for none) and SoundSetEventFile handle, eventIdx, fileName changes it; after the program saves the file, SoundEventsReload makes DVX play the new sounds. SoundTestFile(fileName) plays a file the way DVX plays its event sounds (0 when it cannot, and SoundError$() says why), and SoundFolder$() is the folder of DVX's own sounds. SoundMasterVolume() and SoundSetMasterVolume percent are the volume of all sound from every program. SoundDriverCount() reads the list of sound drivers and SoundDriverName$(index) names each; SoundDriverAuto$() is the setting that means &quot;find the best one&quot;. SoundMidiCount() and SoundMidiLabel$(index) list where MIDI music can play, SoundMidiInCount() and SoundMidiInLabel$(index) where MIDI input can come from, and SoundModulesCount() and SoundModulesLabel$(index) where music modules can play. SoundSettingDriver$(handle), SoundSettingMidi(handle), SoundSettingModules(handle), and SoundSettingVolume(handle) read the sound driver, MIDI choice, modules choice, and master volume from the settings, and SoundSettingsStore handle, driver, midi, modules, volume stores them (a new driver or MIDI choice takes effect when DVX next starts, a modules choice with the next music); SoundSettingMidiIn(handle) and SoundSettingMidiInStore handle, midiIn read and store the MIDI input choice (it takes effect when DVX next starts).</p>
<pre><code>Dim ini As Long
Dim i As Long
@ -5452,8 +5611,12 @@ For i = 0 To SoundEventCount() - 1
Next i</code></pre>
<p><a href="#lang.sound">See: BEEP, SOUND, and PLAY</a></p>
<h2>Music</h2>
<p>With music.bas in the project, a program plays music files: tracker modules (MOD, S3M, XM, and IT files, made of recorded instrument sounds) wherever the computer can play sampled sound, and MIDI files (.MID, types 0 and 1) on the computer's music synthesizer, or on a built-in synthesizer that sounds much the same when there is none. Several programs can play music at once, and everything a program plays stops when it ends.</p>
<p>With music.bas in the project, a program plays music files: tracker modules (MOD, S3M, XM, and IT files, made of recorded instrument sounds) wherever the computer can play sampled sound (on a Gravis UltraSound's or Sound Blaster AWE's own voices, which takes the computer little time), MIDI files (.MID, types 0 and 1) on the computer's music synthesizer, or on a built-in synthesizer that sounds much the same when there is none, and WAV and VOC sound files wherever the computer can play sampled sound (a long WAV recording is read from the disk as it plays, so it needs no memory). Several programs can play music at once, and everything a program plays stops when it ends.</p>
<p>MusicLoad(fileName) loads a music file and returns its music number, or MUSIC_FAILED (0) when it could not be loaded; MusicError$() then says why. MusicPlay(music, loopIt) plays it from where it is (the start after loading or stopping); with loopIt True it starts over at the end until it is stopped. MusicStop(music) stops and goes back to the start, MusicPause(music) and MusicResume(music) pause and go on, and MusicPlaying(music) is True while it plays. MusicVolume(music, volume) sets its volume in percent (0 to 100). MusicPosition(music) and MusicLength(music) give the place and the length in milliseconds, and MusicSeek(music, milliseconds) goes to a place (a module goes to the start of the part that holds it). MusicFree(music) stops a music and forgets it.</p>
<p>MusicLoadMacro(macro) makes a music from a music macro string, the kind PLAY takes, with its notes on the General MIDI instruments its I commands name (the piano before any I): the tune can then be played in the background, paused, stopped, and made quieter like any music. MIDI music plays on the instruments chosen in Control Panel; MusicSetBank music, bank plays one music on another instrument bank, named as in the banks folders (&quot;&quot; is DVX's standard bank), before the music first plays (MusicError$ says when the bank is missing or damaged). A SoundFont (.SF2 or .SBK) gives the recorded instruments for a wavetable card or the built-in SoundFont synthesizer, as can a Gravis UltraSound's own patches: MusicPatchSet$() names them (their ULTRASND.INI, &quot;&quot; when there are none), and MusicRomBank$() names the instruments built into a Sound Blaster AWE card (&quot;&quot; when Creative's software is not installed).</p>
<pre><code>tune = MusicLoadMacro(&quot;T150 I41 O4 L8 CEG&gt;C4&quot;)
MusicSetBank tune, &quot;KPUNCH\DMXOPL.OP2&quot;
MusicPlay tune, False</code></pre>
<pre><code>Dim Shared tune As Long
Sub Form1_Load ()
@ -5482,8 +5645,44 @@ Sub tmrNoteOff_Timer ()
MusicNoteOff keys, 1, 60
tmrNoteOff.Enabled = False
End Sub</code></pre>
<p>MusicGetVolume(music) gives a music's volume in percent. MusicInfo$(music, field) tells about it, by name in any case: &quot;title&quot; (a module's own title), &quot;output&quot; (where it plays, for people), &quot;kind&quot; (&quot;module&quot;, &quot;midi&quot;, or &quot;live&quot;), &quot;where&quot; (&quot;stream&quot;, &quot;mpu401&quot;, &quot;fm&quot;, or &quot;software&quot;; &quot;&quot; before it first plays), and &quot;paused&quot; and &quot;looping&quot; (True or False as text; VAL gives the value).</p>
<p>A program that sends MIDI itself (system exclusive messages, a sequencer of its own) can have the MIDI port, one program at a time, when the settings send MIDI music to the MIDI port. MidiPortInfo$(field) describes it: &quot;description&quot; (&quot;&quot; when there is none), &quot;present&quot;, and &quot;owned&quot; (a program has it). MidiAcquire() takes the port (False when another program has it or there is none), MidiPut(byteValue) sends one byte (False when the port could not take it yet: send it again), and MidiRelease gives the port back.</p>
<p>MusicGetVolume(music) gives a music's volume in percent. MusicInfo$(music, field) tells about it, by name in any case: &quot;title&quot; (a module's own title, or the name a MIDI file gives itself; &quot;&quot; for a sound file), &quot;output&quot; (where it plays, for people), &quot;kind&quot; (&quot;module&quot;, &quot;midi&quot;, &quot;live&quot;, or &quot;sound&quot;), &quot;where&quot; (&quot;stream&quot;, &quot;mpu401&quot;, &quot;fm&quot;, &quot;software&quot;, &quot;wave&quot;, or &quot;softwave&quot;; &quot;wave&quot; is a wavetable card's voices, for a module too; &quot;&quot; before it first plays), and &quot;paused&quot; and &quot;looping&quot; (True or False as text; VAL gives the value).</p>
<p>A program that sends MIDI itself (system exclusive messages, a sequencer of its own) can have the MIDI port, one program at a time, when the settings send MIDI music to the MIDI port. MidiPortInfo$(field) describes it: &quot;description&quot; (&quot;&quot; when there is none), &quot;present&quot;, &quot;owned&quot; (a program has it), &quot;input&quot; (it brings MIDI in), and &quot;inputowned&quot; (a program reads what comes in). MidiAcquire() takes the port (False when another program has it or there is none), MidiPut(byteValue) sends one byte (False when the port could not take it yet: send it again), and MidiRelease gives the port back.</p>
<p>When the settings take MIDI input from the MIDI port (Control Panel, Sounds, MIDI in), a program can read what a MIDI keyboard or another instrument plays. MidiInOpen() starts reading (False when there is no MIDI input or another program reads it; SoundError$() says which) and MidiInClose stops; a program's reading stops when it ends. MidiInMessage() gives the next message that came, or MIDI_NONE (-1) when none waits. A message is packed into one number: the status is midiMsg AND 255 (its kind, midiMsg AND MIDI_KIND_MASK, is MIDI_NOTE_ON, MIDI_NOTE_OFF, MIDI_CONTROL, MIDI_PROGRAM, MIDI_PITCH_BEND, MIDI_KEY_PRESSURE, or MIDI_CHANNEL_PRESSURE, and its channel, numbered as MusicNoteOn numbers them, is (midiMsg AND MIDI_CHANNEL_MASK) + 1), the first data byte (the note) is (midiMsg \ 256) AND 255, and the second (the velocity) (midiMsg \ 65536) AND 255. A note on with a velocity of 0 is a note off too. MidiInTime() is when the message MidiInMessage gave last came and MidiInClock() the time now, both in milliseconds since MidiInOpen; MidiInLost() counts bytes lost because the program read too late. MusicMidiSend music, midiMsg plays a message as it came on a live music (MIDI thru), so what is played is heard.</p>
<p>A MIDI recording keeps messages with their times and saves them as a MIDI file that MusicLoad plays. MidiRecordNew() returns a recording number (0 when there is no room; MusicError$() says why), MidiRecordAdd recording, milliseconds, midiMsg adds a message (MidiInTime() is the time to give, when the recording started with MidiInOpen), MidiRecordCount(recording) and MidiRecordLength(recording) tell how many messages it has and when the last came, MidiRecordSave(recording, fileName) writes the file (False when it could not be written; MusicError$() says why; a note still held at the end is let go), and MidiRecordFree recording frees it. A program's recordings are freed when it ends. The Sound Recorder records a MIDI keyboard this way:</p>
<pre><code>Dim Shared take As Long
Dim Shared keys As Long
Sub cmdRecord_Click ()
If MidiInOpen() Then
take = MidiRecordNew()
keys = MusicMidiOpen()
tmrTake.Enabled = True
End If
End Sub
Sub tmrTake_Timer ()
Dim midiMsg As Long
midiMsg = MidiInMessage()
Do While midiMsg &lt;&gt; MIDI_NONE
MusicMidiSend keys, midiMsg
MidiRecordAdd take, MidiInTime(), midiMsg
midiMsg = MidiInMessage()
Loop
End Sub
Sub cmdStop_Click ()
tmrTake.Enabled = False
MidiInClose
MusicFree keys
If Not MidiRecordSave(take, &quot;SONG.MID&quot;) Then
Print &quot;Not saved: &quot; &amp; MusicError$()
End If
MidiRecordFree take
End Sub</code></pre>
<h2>Network Connections</h2>
<p>With net.bas in the project, a program talks to other computers over the network set up in the Control Panel. TcpConnect returns a handle (0 when it failed; NetError$ says why), TcpSend sends text, and TcpRecv$ returns whatever has arrived without waiting, so a Timer keeps the program responsive:</p>
<pre><code>Dim conn As Long
@ -6012,7 +6211,8 @@ End Sub</code></pre>
CurrentX Single 0 Where the next drawing or printing starts.
CurrentY Single 0
DrawWidth Integer 1 Pen width in pixels.
FillStyle Integer 1 How boxes (B) and circles are filled with FillColor: 0 solid, 1 (the default) not at all, 2 horizontal lines, 3 vertical lines, 4 upward diagonals, 5 downward diagonals, 6 a cross hatch, 7 a diagonal cross hatch (the lines 8 pixels apart, the gaps left as they are). Other values are an error. BF fills solid in the line's colour.
DrawStyle Integer 0 The pen's lines and outlines: 0 solid, 1 dashes, 2 dots, 3 dash-dot, 4 dash-dot-dot (a pen 1 pixel wide only; a wider one draws solid), 5 none at all (fills are still drawn), 6 solid. Other values are an error. The constants vbSolid to vbInsideSolid name them.
FillStyle Integer 1 How boxes (B) and circles are filled with FillColor: 0 solid, 1 (the default) not at all, 2 horizontal lines, 3 vertical lines, 4 upward diagonals, 5 downward diagonals, 6 a cross hatch, 7 a diagonal cross hatch (the lines 8 pixels apart, the gaps left as they are). Other values are an error. BF fills solid in the line's colour. The constants vbFSSolid to vbDiagonalCross name them.
FillColor Long &amp;H000000 Colour boxes and circles are filled with.
FontScale Integer 1 How many times as large Print writes its text (1 to 8): each dot of the font becomes a FontScale x FontScale block, for titles and banners. TextWidth and TextHeight follow it; PrintAccel does not.
AutoRedraw Boolean False True: no Paint events (see above).
@ -6425,7 +6625,7 @@ Dim g As New Form1 ' declares and makes a copy at once</code></pre>
End If
End Sub</code></pre>
<h2>Drawing</h2>
<p>Forms have Visual Basic's drawing methods and properties (Cls, PSet, Line, Circle, Point, Print, PaintPicture, DrawFocusRect, DrawBevel, DrawButtonFace, DrawArrow, DrawScrollBar, DrawScrollArrow, ScrollBarClick, ScrollBarsNeeded, PrintAccel, Scale, CurrentX, CurrentY, ForeColor, BackColor, DrawWidth, FillColor, FillStyle, FontScale, AutoRedraw, ScaleMode, ScaleLeft, ScaleTop, ScaleWidth, ScaleHeight): see Drawing on Forms and PictureBoxes. In the form's own code use Me.Line, Me.Circle, and so on.</p>
<p>Forms have Visual Basic's drawing methods and properties (Cls, PSet, Line, Circle, Point, Print, PaintPicture, DrawFocusRect, DrawBevel, DrawButtonFace, DrawArrow, DrawScrollBar, DrawScrollArrow, ScrollBarClick, ScrollBarsNeeded, PrintAccel, Scale, CurrentX, CurrentY, ForeColor, BackColor, DrawWidth, DrawStyle, FillColor, FillStyle, FontScale, AutoRedraw, ScaleMode, ScaleLeft, ScaleTop, ScaleWidth, ScaleHeight): see Drawing on Forms and PictureBoxes. In the form's own code use Me.Line, Me.Circle, and so on.</p>
<h2>Example</h2>
<pre><code>Sub Form1_Load ()
Form1.Caption = &quot;Hello World&quot;
@ -6526,7 +6726,7 @@ End Sub</code></pre>
PropertyChanged name Tells a designer that a property changed, so its property sheet shows the new value.
Cls, Line, PSet, Circle, Print, Point, PaintPicture, DrawFocusRect, TextWidth, TextHeight, Scale, ScaleX, ScaleY Drawing, as on a PictureBox.
DrawBevel, DrawButtonFace, DrawArrow, DrawScrollBar, DrawScrollArrow, ScrollBarClick, ScrollBarsNeeded, PrintAccel, TextWidthAccel, AccelKey Drawing in DVX's own look (bevels, button faces, arrows, upright and horizontal scroll bars and their arrow buttons, captions with an underlined access key), as on a PictureBox.
CurrentX, CurrentY, ForeColor, BackColor, FillColor, FillStyle, FontScale, DrawWidth, AutoRedraw, ScaleMode, ScaleLeft, ScaleTop, ScaleWidth, ScaleHeight Drawing properties, as on a PictureBox.</pre>
CurrentX, CurrentY, ForeColor, BackColor, FillColor, FillStyle, FontScale, DrawWidth, DrawStyle, AutoRedraw, ScaleMode, ScaleLeft, ScaleTop, ScaleWidth, ScaleHeight Drawing properties, as on a PictureBox.</pre>
<p>The drawing members work exactly as on a PictureBox (see Drawing on Forms and PictureBoxes). Write them with UserControl in front -- UserControl.Line, UserControl.Print -- as a form's code writes Me.Line: a drawing statement on its own (Line, Cls, Print) draws on the program's screen, not on the control.</p>
<p>The drawing stays until you draw again. UserControl_Paint runs when the control first appears, after its size changed, when you call Refresh, and after you call Invalidate; draw everything there and call UserControl.Invalidate (or UserControl.Refresh, to see the result at once) whenever what it shows changes.</p>
<h2>The Control's Events</h2>

File diff suppressed because it is too large Load diff

View file

@ -59,6 +59,9 @@
# toolchains/fonts which pins them): FreeType for the font converter,
# built from source, and every font DVX converts
# and ships, with its licence (src/fonts/sources.txt)
# toolchains/soundfonts the SoundFonts the bank add-ons are made from
# (src/addons/banks/installSoundFonts.sh, which pins
# them): FluidR3_GM, for the dvxgm add-on
#
# Every download is checked against a pinned SHA-256 before it is unpacked,
# so a changed or corrupted archive is refused instead of installed.
@ -346,13 +349,20 @@ else
"${ROOT}/src/fonts/installFonts.sh"
fi
# The SoundFonts the bank add-ons are made from, pinned in their own script
if [ "${FORCE}" -eq 1 ]; then
"${ROOT}/src/addons/banks/installSoundFonts.sh" --force
else
"${ROOT}/src/addons/banks/installSoundFonts.sh"
fi
# Verify what the build needs.
if [ "$("${DJGPP_GCC}" -dumpfullversion)" != "${DJGPP_VERSION}" ]; then
echo "installToolchain: ${DJGPP_GCC} is not GCC ${DJGPP_VERSION}" >&2
exit 1
fi
for f in "${DJGPP_DIR}/i586-pc-msdosdjgpp/bin/dxe3gen" "${DJGPP_DIR}/i586-pc-msdosdjgpp/bin/exe2coff" "${CWSDSTUB}" "${UPX_BIN}" "${BOX86_BIN}" "${BOX86_ROMS}/machines" "${FREEDOS_DIR}/MBR.BIN" "${FREEDOS_DIR}/BOOTSECT.BIN" "${FREEDOS_DIR}/KERNEL.SYS" "${FREEDOS_DIR}/COMMAND.COM" "${FREEDOS_DIR}/HIMEMX.EXE" "${FREEDOS_DIR}/UDVD2.SYS" "${FREEDOS_DIR}/SHSUCDX.COM" "${FREEDOS_DIR}/CTMOUSE.EXE" "${DOSBOX_BIN}" "${CPPCHECK_BIN}" "${TOOLCHAINS}/lrzsz/bin/lsz" "${TOOLCHAINS}/pktdrv/NE2000.COM" "${TOOLCHAINS}/emu8950/emu8950.c" "${TOOLCHAINS}/soundfont/TimGM6mb.sf2" "${TOOLCHAINS}/freetype/lib/libfreetype.a" "${TOOLCHAINS}/fonts/.installed"; do
for f in "${DJGPP_DIR}/i586-pc-msdosdjgpp/bin/dxe3gen" "${DJGPP_DIR}/i586-pc-msdosdjgpp/bin/exe2coff" "${CWSDSTUB}" "${UPX_BIN}" "${BOX86_BIN}" "${BOX86_ROMS}/machines" "${FREEDOS_DIR}/MBR.BIN" "${FREEDOS_DIR}/BOOTSECT.BIN" "${FREEDOS_DIR}/KERNEL.SYS" "${FREEDOS_DIR}/COMMAND.COM" "${FREEDOS_DIR}/HIMEMX.EXE" "${FREEDOS_DIR}/UDVD2.SYS" "${FREEDOS_DIR}/SHSUCDX.COM" "${FREEDOS_DIR}/CTMOUSE.EXE" "${DOSBOX_BIN}" "${CPPCHECK_BIN}" "${TOOLCHAINS}/lrzsz/bin/lsz" "${TOOLCHAINS}/pktdrv/NE2000.COM" "${TOOLCHAINS}/emu8950/emu8950.c" "${TOOLCHAINS}/soundfont/TimGM6mb.sf2" "${TOOLCHAINS}/freetype/lib/libfreetype.a" "${TOOLCHAINS}/fonts/.installed" "${TOOLCHAINS}/soundfonts/FluidR3_GM.sf2"; do
if [ ! -e "${f}" ]; then
echo "installToolchain: expected file missing after install: ${f}" >&2
exit 1

BIN
screenshots/86box/addons-addon-no.png (Stored with Git LFS)

Binary file not shown.

BIN
screenshots/86box/apps-clock.png (Stored with Git LFS)

Binary file not shown.

BIN
screenshots/86box/apps-cpanel.png (Stored with Git LFS)

Binary file not shown.

BIN
screenshots/86box/apps-desktop.png (Stored with Git LFS)

Binary file not shown.

BIN
screenshots/86box/apps-dvxbasic.png (Stored with Git LFS)

Binary file not shown.

BIN
screenshots/86box/apps-dvxhelp.png (Stored with Git LFS)

Binary file not shown.

BIN
screenshots/86box/apps-iconed.png (Stored with Git LFS)

Binary file not shown.

BIN
screenshots/86box/apps-imgview.png (Stored with Git LFS)

Binary file not shown.

BIN
screenshots/86box/apps-notepad.png (Stored with Git LFS)

Binary file not shown.

BIN
screenshots/86box/apps-player.png (Stored with Git LFS) Normal file

Binary file not shown.

BIN
screenshots/86box/apps-resedit.png (Stored with Git LFS)

Binary file not shown.

BIN
screenshots/86box/banked-bk-back.png (Stored with Git LFS)

Binary file not shown.

BIN
screenshots/86box/banked-bk-desk.png (Stored with Git LFS)

Binary file not shown.

BIN
screenshots/86box/banked-bk-drag.png (Stored with Git LFS)

Binary file not shown.

BIN
screenshots/86box/banked-bk-note.png (Stored with Git LFS)

Binary file not shown.

BIN
screenshots/86box/boot-boot.png (Stored with Git LFS)

Binary file not shown.

BIN
screenshots/86box/cpanel-cp-color.png (Stored with Git LFS)

Binary file not shown.

BIN
screenshots/86box/cpanel-cp-desk.png (Stored with Git LFS)

Binary file not shown.

BIN
screenshots/86box/cpanel-cp-joy.png (Stored with Git LFS)

Binary file not shown.

BIN
screenshots/86box/cpanel-cp-mouse.png (Stored with Git LFS)

Binary file not shown.

BIN
screenshots/86box/cpanel-cp-net.png (Stored with Git LFS)

Binary file not shown.

BIN
screenshots/86box/cpanel-cp-print.png (Stored with Git LFS)

Binary file not shown.

BIN
screenshots/86box/cpanel-cp-sound.png (Stored with Git LFS)

Binary file not shown.

BIN
screenshots/86box/cpanel-cp-types.png (Stored with Git LFS)

Binary file not shown.

BIN
screenshots/86box/cpanel-cp-video.png (Stored with Git LFS)

Binary file not shown.

BIN
screenshots/86box/dosprog-dp-after.png (Stored with Git LFS) Normal file

Binary file not shown.

BIN
screenshots/86box/dosprog-dp-ask.png (Stored with Git LFS) Normal file

Binary file not shown.

BIN
screenshots/86box/dosprog-dp-back.png (Stored with Git LFS) Normal file

Binary file not shown.

BIN
screenshots/86box/exit-cancel.png (Stored with Git LFS)

Binary file not shown.

BIN
screenshots/86box/exit-savechg.png (Stored with Git LFS)

Binary file not shown.

BIN
screenshots/86box/f1-h-basdem.png (Stored with Git LFS)

Binary file not shown.

BIN
screenshots/86box/f1-h-clock.png (Stored with Git LFS)

Binary file not shown.

BIN
screenshots/86box/f1-h-cpanel.png (Stored with Git LFS)

Binary file not shown.

BIN
screenshots/86box/f1-h-iconed.png (Stored with Git LFS)

Binary file not shown.

BIN
screenshots/86box/f1-h-imgvie.png (Stored with Git LFS)

Binary file not shown.

BIN
screenshots/86box/f1-h-notepa.png (Stored with Git LFS)

Binary file not shown.

BIN
screenshots/86box/f1-h-player.png (Stored with Git LFS) Normal file

Binary file not shown.

BIN
screenshots/86box/f1-h-progmn.png (Stored with Git LFS)

Binary file not shown.

BIN
screenshots/86box/f1-h-resedi.png (Stored with Git LFS)

Binary file not shown.

BIN
screenshots/86box/filedlg-fd-back.png (Stored with Git LFS)

Binary file not shown.

BIN
screenshots/86box/filedlg-fd-list.png (Stored with Git LFS)

Binary file not shown.

BIN
screenshots/86box/filedlg-fd-nordy.png (Stored with Git LFS)

Binary file not shown.

BIN
screenshots/86box/filedlg-fd-open.png (Stored with Git LFS)

Binary file not shown.

BIN
screenshots/86box/fullmode-fm-desk.png (Stored with Git LFS)

Binary file not shown.

BIN
screenshots/86box/fullscr-fs-desk.png (Stored with Git LFS)

Binary file not shown.

BIN
screenshots/86box/hang-ended.png (Stored with Git LFS)

Binary file not shown.

BIN
screenshots/86box/hang-taskmgr.png (Stored with Git LFS)

Binary file not shown.

BIN
screenshots/86box/install-in-desk.png (Stored with Git LFS)

Binary file not shown.

BIN
screenshots/86box/lfn-lfnsmk.png (Stored with Git LFS)

Binary file not shown.

BIN
screenshots/86box/menus-m-altdn.png (Stored with Git LFS)

Binary file not shown.

BIN
screenshots/86box/menus-m-altup.png (Stored with Git LFS)

Binary file not shown.

BIN
screenshots/86box/menus-m-design.png (Stored with Git LFS)

Binary file not shown.

BIN
screenshots/86box/menus-m-drop.png (Stored with Git LFS)

Binary file not shown.

BIN
screenshots/86box/menus-m-file.png (Stored with Git LFS)

Binary file not shown.

BIN
screenshots/86box/menus-m-run.png (Stored with Git LFS)

Binary file not shown.

BIN
screenshots/86box/midiin-rc-midi.png (Stored with Git LFS) Normal file

Binary file not shown.

BIN
screenshots/86box/net-netsmk.png (Stored with Git LFS)

Binary file not shown.

BIN
screenshots/86box/pardsgn-pardsgn.png (Stored with Git LFS)

Binary file not shown.

BIN
screenshots/86box/parhlp-parhlp-l.png (Stored with Git LFS)

Binary file not shown.

BIN
screenshots/86box/parhlp-parhlp.png (Stored with Git LFS)

Binary file not shown.

BIN
screenshots/86box/parpm-parpm.png (Stored with Git LFS)

Binary file not shown.

BIN
screenshots/86box/paths-paths.png (Stored with Git LFS)

Binary file not shown.

BIN
screenshots/86box/player-p-mid.png (Stored with Git LFS) Normal file

Binary file not shown.

BIN
screenshots/86box/player-p-mod.png (Stored with Git LFS) Normal file

Binary file not shown.

BIN
screenshots/86box/player-p-voc.png (Stored with Git LFS) Normal file

Binary file not shown.

BIN
screenshots/86box/player-p-wav.png (Stored with Git LFS) Normal file

Binary file not shown.

BIN
screenshots/86box/print-print1.png (Stored with Git LFS)

Binary file not shown.

BIN
screenshots/86box/record-rc-open.png (Stored with Git LFS) Normal file

Binary file not shown.

BIN
screenshots/86box/safevid-sv-desk.png (Stored with Git LFS)

Binary file not shown.

BIN
screenshots/86box/saver-sv-back.png (Stored with Git LFS) Normal file

Binary file not shown.

BIN
screenshots/86box/saver-sv-blank.png (Stored with Git LFS) Normal file

Binary file not shown.

BIN
screenshots/86box/saver-sv-cpd.png (Stored with Git LFS) Normal file

Binary file not shown.

BIN
screenshots/86box/sdk-h-sdkapp.png (Stored with Git LFS)

Binary file not shown.

BIN
screenshots/86box/sdk-sdkapp.png (Stored with Git LFS)

Binary file not shown.

BIN
screenshots/86box/sdk-sdkbas.png (Stored with Git LFS)

Binary file not shown.

BIN
screenshots/86box/sdk-sdkgreet.png (Stored with Git LFS)

Binary file not shown.

BIN
screenshots/86box/sdk-sdktbx.png (Stored with Git LFS)

Binary file not shown.

BIN
screenshots/86box/sdkgame-sdkgame.png (Stored with Git LFS)

Binary file not shown.

BIN
screenshots/86box/software-sw-done.png (Stored with Git LFS)

Binary file not shown.

BIN
screenshots/86box/software-sw-plan.png (Stored with Git LFS)

Binary file not shown.

BIN
screenshots/86box/sql-sqlsmk.png (Stored with Git LFS)

Binary file not shown.

BIN
screenshots/86box/ucdemo-ucdemo.png (Stored with Git LFS)

Binary file not shown.

BIN
screenshots/86box/ucide-ucide-ds.png (Stored with Git LFS)

Binary file not shown.

BIN
screenshots/86box/ucide-ucide-ru.png (Stored with Git LFS)

Binary file not shown.

BIN
screenshots/86box/ucide-ucide-tb.png (Stored with Git LFS)

Binary file not shown.

BIN
screenshots/86box/video-v-800.png (Stored with Git LFS)

Binary file not shown.

BIN
screenshots/86box/video-v-pick.png (Stored with Git LFS)

Binary file not shown.

BIN
screenshots/86box/winops-w-back.png (Stored with Git LFS)

Binary file not shown.

BIN
screenshots/86box/winops-w-min.png (Stored with Git LFS)

Binary file not shown.

BIN
screenshots/86box/winops-w-move.png (Stored with Git LFS)

Binary file not shown.

BIN
screenshots/86box/winops-w-rest.png (Stored with Git LFS)

Binary file not shown.

BIN
screenshots/86box/winops-w-size.png (Stored with Git LFS)

Binary file not shown.

Some files were not shown because too many files have changed in this diff Show more