THOREAU BASIC 2.5.2 =================== Homepage : https://thoreaubasic.com Itch site: https://tarjan.itch.io/thoreaubasic Mail : info@thoreaubasic.com A 64-bit BASIC interpreter for x64 Windows and x64 UEFI. Thoreau BASIC keeps the direct, line-numbered style of classic Microsoft BASIC, adds modern 64-bit memory and graphics, and can run either as a Windows program or directly from UEFI firmware without an operating system. Version 2.5.2 is a runtime-performance and robustness update built around repeated JIT/PARFOR workloads. Windows and UEFI now reuse compiled PARFOR source regions instead of allocating another cached region on every invocation, RUN flushes token/JIT state before variables are recreated, and queued gameplay key events are discarded when RUN or CONT returns to Ready so old KEYDOWN/INKEY$ events cannot surface later in the editor or LIST pager. On x64 UEFI, PARFOR now uses a persistent worker pool for the duration of a running BASIC program. Application processors are started through EFI MP Services only when the pool grows; later PARFOR jobs are handed to the parked workers through shared generation/work counters while the BSP participates as a worker too. This removes firmware AP-start/event/barrier overhead from repeated parallel loops. On supported processors Thoreau can enable OSXSAVE/YMM state itself on bare metal so AVX2-capable JIT paths are usable even when firmware left that state disabled. UEFI also reports framebuffer write-combining status and has a bulk fast path for graphics PUT ...,PSET presentation. Island3D joins the showcase programs in 2.5.2. It renders a first-person fractal heightfield with a 1024x1024 terrain grid by default, distance fog, directional lighting, trees and a double-buffered PARFOR column renderer. The running demo needs only a mouse: movement of the mouse looks around, the left button walks forward, the right button walks backward. Version 2.5.1 extends the native-execution engine with explicit multicore BASIC. PARFOR has the familiar FOR/NEXT shape but divides independent iterations among several CPU threads when the loop can be proven safe for parallel execution. Windows uses a persistent worker pool; the original 2.5.1 UEFI implementation uses firmware MP Services and lets the BSP participate. PARFOR shares one compiled native graph between workers, schedules work in chunks, keeps ordinary numeric and @ scalar scratch state private to each worker, and permits carefully proven disjoint array and framebuffer writes. OPTION PARTHREADS controls the worker limit and PARWORKERS reports the effective count used by the most recent parallel loop. Version 2.5.1 also continues the JIT performance work: native integer FOR/NEXT, more direct graphics paths, JIT-preserving PRINT/LOCATE callouts, shared PARFOR code, reduced parallel graphics bookkeeping and selected AVX2 acceleration when the CPU/OS environment supports it, with SSE2 fallback. Startup diagnostics now show keyboard capabilities, PARFOR thread capacity and SIMD availability. Octal numeric literals using GW-BASIC-style &O syntax are accepted. The 2.5 GorseGlass raytracer remains the main JIT/PARFOR stress test. Version 2.5 introduced the production x64 bytecode/JIT engine on both Windows and UEFI. Hot numeric and hypercomplex expressions, scalar and numeric/@ array access, assignments, IF/ELSE, FOR/NEXT, WHILE/WEND, DEF FN, selected graphics statements and large cross-line program regions can execute as generated x64 code. Classic GOSUB/RETURN-heavy BASIC is supported across compiled regions, including calls inside native loops and single-line IF branches. Unsupported syntax falls back to the existing interpreter automatically rather than changing program semantics. JIT is ON by default; JIT OFF forces the classic interpreter for correctness A/B tests, and PROFILE is JIT-aware. Version 2.4.1 was a development, control-flow and graphics-polish release. It added syntax-aware source tools (enhanced FIND, REPLACE, XREF and AUDIT), a statement profiler, explicit FOR END and WHILE END loop exits, REDIM, graphics slot introspection, POLYFILL, GW-BASIC DRAW P filling and an interactive Ctrl+L clear-screen shortcut. FOR and WHILE stacks each allow 4096 active loops, and mouse-click event delivery was hardened so rapid edge events are not lost between interpreter polls. Version 2.4 adds cross-platform mouse input, held-key state for simultaneous game controls, flexible video-mode discovery, and TCP/IPv4 networking with DNS and HTTP/HTTPS helpers. Windows can now use arbitrary logical framebuffer sizes and scale them into a window or fullscreen display with preserved aspect ratio. UEFI exposes real GOP modes and uses standard firmware pointer and network protocols where the machine provides them, with a raw SNP network fallback when higher-level UEFI network services are unavailable. Version 2.4 also closes several subtle GW-BASIC compatibility gaps: a leading semicolon on INPUT can suppress the final newline, NEXT can name several loop variables, and DEFINT/DEFSNG/DEFDBL/DEFLNG/DEFI64/DEFSTR now make an unsuffixed name and its matching explicit suffix refer to the same variable. Version 2.3.1 was a compatibility, debugging and usability update. It added the lazy IIF conditional expression, corrected nested single-line IF/ELSE execution, expanded the Thoreau Machine Explorer into a live debugger, reported the source line reached by STOP, and tightened program loading, directory output and Windows file-handle lifetime. Version 2.3 adds two substantial new language areas: software sprites for games and a native hypercomplex @ numeric type for higher mathematics. Sprite images and instances are separate, allowing up to 65,536 loaded images and 65,536 independent instances while many instances share one image in memory. Sprites support movement, visibility, text layering and pixel-perfect collision using precomputed transparency masks. Version 2.3 also adds game-oriented KEYREPEAT and WAITREL timing controls. The @ type covers complex numbers, quaternions and octonions in one numeric promotion tower. CPLX, QUAT and OCT construct values; arithmetic, conjugation, inverse, norm, component access and @ arrays are integrated into the expression engine. Version 2.3 also extends ^, SIN, COS, TAN, EXP, LOG, SQR/SQRT, SINH, COSH and TANH to @ values, with explicit principal-value rules where the mathematics is multivalued. Version 2.2 was primarily a compatibility, robustness and memory-management release. It added SAVEBMP, wildcard KILL, parenthesized BITBLT coordinates, automatic .BAS on SAVE, interruptible recursive DIR/FILES, compacting string garbage collection, reusable/coalescing array and bitmap memory, classic two-byte extended-key INKEY$ results, and full-width word-aware HELP. Version 2.1 adds international keyboard support to the x64 UEFI build, runtime keyboard-layout switching, and the SYSTEM command on both platforms. On UEFI, THOREAU.CFG beside the EFI can contain a DOS-style keyboard selection: KEYB GR KEYB can also switch layouts while Thoreau BASIC is running. Thoreau supports 23 layouts. When possible it reads a USB HID boot keyboard directly so physical key positions are preserved even when firmware keyboard translation is incomplete. If direct USB HID input is unavailable, it falls back to UEFI firmware input. The default layout is US. SYSTEM leaves Thoreau BASIC. On Windows it closes the application. On UEFI it returns to the firmware/caller, allowing normal firmware boot processing to continue when Thoreau was started as a boot option. Version 2.1 also includes the 2.01 compatibility refinements: RUN accepts a starting line or filename, AUTO preserves an existing line when Enter is pressed immediately at its * prompt, and bitmap slots range from 0 through 65535. Version 2.0 added standalone application creation: Windows: CREATEEXE "program" UEFI: CREATEEFI "program" The generated EXE/EFI contains the currently loaded BASIC program. When the generated application starts, it skips the normal Thoreau BASIC banner and command prompt and immediately runs the embedded program. External assets such as BMP files and save files remain ordinary files beside the application. VERSION 2.5.2 CHANGES ===================== Version 2.5.2 concentrates on making long-running and repeatedly invoked JIT workloads behave like a runtime rather than a sequence of fresh compilations. - Repeated PARFOR source regions are cached by source location, callable mode and bytecode epoch. A loop executed once per frame therefore reuses its compiled region graph instead of consuming more of the code/token arena on every frame. - RUN is a compile-cache boundary. Thoreau flushes token/bytecode/native-JIT cache state before BASreset recreates variables and arrays, preventing stale cached variable identities from surviving into a second RUN. - Windows and UEFI discard queued gameplay key events when RUN or CONT returns to Ready. KEYDOWN remains non-consuming while a program runs, but keypresses accumulated by a game no longer reappear later in the command editor, INKEY$, INPUT$, or a LIST paging prompt. - x64 UEFI PARFOR now keeps a persistent application-processor worker pool for the lifetime of a BASIC RUN. APs are started through EFI MP Services only when the pool grows; later PARFOR jobs are published through shared generation/work counters. The BSP remains a worker. This removes repeated StartupThisAP/event creation/firmware wait overhead from frame-by-frame parallel loops. - On bare-metal x64 UEFI, Thoreau can enable CR4.OSXSAVE and the SSE/YMM XCR0 state itself when CPUID reports XSAVE, AVX and AVX2 support. The startup diagnostic distinguishes AVX2 hardware whose YMM state was enabled by Thoreau from environments where it was already enabled. Each persistent AP initializes its own processor state when it joins the PARFOR pool. - UEFI startup also reports whether the GOP framebuffer was successfully set to write-combining memory. Graphics PUT ...,PSET has a bulk SSE2 copy path with non-temporal stores to the visible framebuffer, reducing full-frame presentation overhead. - Island3D is added as a 2.5.2 showcase for the combined JIT, PARFOR, mouse and graphics paths. The supplied configuration uses a 640x480 view over a 1024x1024 fractal heightfield (VOX=4), with fog, directional terrain lighting, trees and a double-buffered parallel column renderer. VERSION 2.5.1 CHANGES ===================== Version 2.5.1 focuses on parallel execution and further JIT/runtime performance without changing the classic interpreter semantics. - PARFOR adds explicit data/iteration parallelism using familiar BASIC syntax: PARFOR Y=0 TO GRAMAXY ...independent work for Y... NEXT Y PARFOR is intentionally opt-in. Ordinary FOR retains its normal sequential semantics. A PARFOR body must stay fully JIT-compilable and every iteration must be safe to execute independently. The compiler validates the complete reachable control-flow/GOSUB graph before starting workers and rejects unsafe loops with a source-aware explanation, the offending command and a suggested workaround. - Numeric and @ scalar variables used as PARFOR scratch state are private to each worker. Shared numeric/@ arrays may be read normally. Array stores are accepted only when Thoreau can prove them disjoint between iterations, for example A(I)=... under PARFOR I or B(X,I)=... under PARFOR I. Ambiguous shared writes are rejected rather than raced. - Absolute PSET and supported LINE forms with explicit colours can be used as PARFOR output when iterations draw independent pixels/regions. WINDOW/VIEW dependent drawing is rejected because it relies on shared transform state. Text output/cursor operations and other shared interpreter state remain outside PARFOR. - PARFOR currently supports integer start/limit values and a positive integer STEP. Nested PARFOR is deliberately rejected. JIT must be ON; PROFILE, tracing, debugger breakpoints and interpreter event handlers must be disabled while a PARFOR executes because their runtime state is shared. - OPTION PARTHREADS 0 selects automatic worker tuning. Small loops may stay on one worker when parallel launch/barrier cost would be larger than the work. OPTION PARTHREADS n (1..32) caps the requested worker count. PARTHREADS reads the configured value; PARWORKERS reports the effective number used by the most recent PARFOR. Startup also reports how many CPU threads are available to PARFOR on the current machine/firmware. - Windows uses a persistent PARFOR worker pool. UEFI uses EFI MP Services and includes the BSP as a worker when possible. Workers dynamically claim chunks of iterations, reducing synchronization overhead while preserving load balancing. The same position-independent native PARFOR graph is shared by all workers instead of compiling one code copy per worker. - Parallel framebuffer drawing avoids needless per-pixel updates of shared graphics bookkeeping and consolidates those updates at the PARFOR barrier, reducing cache-line contention between cores. - The JIT gains native fast paths for horizontal/vertical LINE, boxes and filled boxes where semantics permit; PRINT and LOCATE can call the canonical statement implementation without tearing down an otherwise native region; and integer FOR/NEXT now has a corrected native fast path. - Selected hypercomplex component operations can use AVX2 when the processor and execution environment expose usable AVX2/YMM state. SSE2 remains the baseline fallback. Startup reports which SIMD path is available to the JIT. - Startup diagnostics are grouped into keyboard, CPU/PARFOR and SIMD blocks. Keyboard output identifies the active backend and whether KEYDOWN and KEYREPEAT delay/rate control are available. - GW-BASIC-style octal literals are accepted with &O, for example &O10 (8) and &O377 (255), alongside the existing &H hexadecimal syntax. - PARFOR diagnostic messages wrap to the active text-window width so their detailed reason/workaround text remains readable on narrow screens. - SPRITEOFF is documented: it deletes all active sprite instances at once but keeps loaded sprite images available for later SPRITE commands. VERSION 2.5 CHANGES =================== Version 2.5 turns the experimental bytecode/JIT work into a normal execution engine on Windows x64 and x64 UEFI. The classic interpreter remains the semantic fallback and can be forced explicitly with JIT OFF. - JIT is enabled by default. JIT ON enables all bytecode/native acceleration; JIT OFF forces the classic interpreter for expressions, assignments, control flow, loops and compiled program regions. Bare JIT reports the current state. Changing the state flushes native JIT pages. - Stored-program expressions and statements can be compiled once and reused. The production engine covers scalar numeric arithmetic/comparisons, native @ hypercomplex operations, DEF FN expression bodies, numeric/@ arrays, scalar assignments, IF/ELSE, FOR/NEXT and WHILE/WEND, plus selected graphics paths including PSET/PRESET, LINE and COLOR. Unsupported syntax simply falls back. - Cross-line PROGRAM regions keep larger stretches of ordinary line-numbered BASIC in compiled execution rather than accelerating isolated expressions only. Nested single-line IF constructs preserve nearest-ELSE semantics. - Literal GOSUB/RETURN is supported inside compiled regions. Cross-region subroutine calls are preflighted and can execute synchronously without dropping native FOR/WHILE state. When a call must fall back to the classic interpreter, its BASIC return point and single-line IF context are preserved. - The JIT includes native handling and caching aimed at classic loop-heavy BASIC: numeric/@ arrays, FOR/NEXT regions, hypercomplex arithmetic, small integer powers, repeated subroutine targets and reusable compiled blocks. - PROFILE is JIT-aware. PROFILE ON, PROFILE JIT and PROFILE SAMPLE use the compiled engine with randomized low-overhead timing samples. PROFILE EXACT and PROFILE INTERPRETER use exact interpreter timing and disable compiled fast paths while profiling. Reports include RUNS, JITRUNS, INTRUNS and MODE; MODE distinguishes JIT, INT and mixed execution. PROFILE MARK (also PROFILE MARK ON or PROFILE ON MARK) starts the normal JIT-aware sampled profiler and records which engine executed each statement for colour-coded LIST output. Green means executed by JIT; yellow means interpreted although the statement itself is JIT-capable; red means interpreted and not JIT-supported; normal text means the statement was not reached. PROFILE MARK OFF restores ordinary LIST colours without discarding collected statistics. PROFILE OFF retains samples and the last MARK colours; PROFILE CLEAR discards statistics and marks. - Windows allocates executable JIT pages through the native virtual-memory layer. UEFI allocates runtime-generated code as EfiLoaderCode pages through Boot Services and releases them when the JIT cache is flushed. - JIT OFF is deliberately broader than a native-code switch: it disables the bytecode VM too. This provides a clean interpreter-vs-JIT correctness test. - GorseGlass is added as a v2.5 showcase and stress test. It renders a 1024x768 scene with analytic spheres, a checkerboard floor, hard shadows, Phong highlights, reflection, true entry/exit Snell refraction and Schlick Fresnel blending. The distributed version keeps the visually stronger quality path. VERSION 2.4.1 CHANGES ===================== Version 2.4.1 concentrates on development ergonomics, structured exits, arrays and graphics convenience while retaining the 2.4 language and platform model. - FIND gains FIND NEXT and FIND PREV to continue the previous search, optional WORD matching for complete BASIC identifiers, and the existing line-range restriction. Ordinary FIND remains a case-insensitive textual search and therefore still sees strings and comments. - REPLACE old$,new$[,range][,WORD] edits stored source directly. Plain mode performs case-insensitive literal replacement. WORD mode is intended for safe symbol renaming: it requires BASIC names and ignores quoted strings, REM/apostrophe comments and DATA. Replacement is preflighted so an overlong source line or full code arena leaves the program unchanged. - XREF name, XREF array() and XREF line provide syntax-aware cross-reference searches. The line form follows literal GOTO, GOSUB, THEN, ELSE, RESTORE, RESUME and ON targets and reports whether the target line exists. - AUDIT performs a static source pass for undefined literal line targets, source-order FOR/NEXT and WHILE/WEND mismatches, and parenthesized FN calls that have no DEF FN. Strings, comments and DATA are ignored. - PROFILE ON clears and starts line profiling; PROFILE OFF stops measurement while retaining samples; PROFILE shows the 20 hottest lines; PROFILE ALL prints all sampled lines in source order; PROFILE CLEAR discards samples. Output uses aligned LINE/RUNS/TIME/SHARE/SOURCE columns. - FOR END exits the innermost active FOR and continues after its matching NEXT. WHILE END does the same for WHILE/WEND. FOR and WHILE runtime stacks now each permit 4096 active loops. - REDIM array(bounds) creates an array if absent or replaces an existing one. Existing contents are discarded and the array address may change. ERASE of a nonexistent array is now harmless, simplifying subprograms that allocate result arrays on demand. - POLYFILL fills arbitrary polygons with the even-odd rule and accepts palette colors, packed 24-bit RGB or r,g,b triples. STEP vertices are relative to the previous vertex. Up to 4096 vertices are accepted. - DRAW adds the classic Ppaint,border Graphics Macro Language command, using the same flood-fill engine as PAINT. - Bitmap slots can be queried with BMPLOADED(), BMPWIDTH() and BMPHEIGHT(). Sprite-image slots add SPRITELOADED(), SPRITEWIDTH(), SPRITEHEIGHT() and SPRITEKEYCOLOR(). LOADBMP has no stored key color because BITBLT transparency is selected per draw operation. - SCREEN(row,col) returns the character code stored in a text cell. There is no PC-style attribute-byte form because Thoreau's display is a 24-bit framebuffer with a separate text grid rather than VGA text memory. - Ctrl+L at the interactive prompt clears the display and the current edit line. It is not an asynchronous CLS shortcut while a BASIC program runs. - ON MOUSECLICK delivery now queues button-down edges so clicks are not lost merely because several arrive between interpreter statement polls. VERSION 2.4 CHANGES =================== Version 2.4 extends Thoreau BASIC in four practical areas: input, video, networking and compatibility. - KEYDOWN(key$) reports whether a key is currently held without consuming INKEY$. Multiple keys can therefore be tested in the same game frame. Named keys include LEFT, RIGHT, UP, DOWN, SPACE, ENTER, ESC, TAB, HOME, END, INSERT, DELETE, PAGEUP, PAGEDOWN, SHIFT, CTRL, ALT and F1 through F12. Single-character strings and classic CHR$(0)+scan extended-key strings are accepted too. KEYSTATEAVAILABLE reports whether genuine held-key state is available. Windows always provides it while the Thoreau window is active; UEFI provides it through the raw USB HID keyboard backend. Firmware text input cannot provide reliable key-release state. - Mouse support is available on both platforms. MOUSE ON/OFF controls pointer visibility, MOUSEPOS sets its logical position, and MOUSEX(), MOUSEY(), MOUSEB(), MOUSEWHEEL() and MOUSEPRESENT expose state. Windows uses the native pointer. UEFI uses EFI_SIMPLE_POINTER_PROTOCOL with EFI_ABSOLUTE_POINTER_PROTOCOL fallback and draws a 12x18 black/white software pointer as a topmost layer, so moving it does not damage BASIC graphics. - ON MOUSEMOVE GOSUB line and ON MOUSECLICK GOSUB line provide non-preemptive mouse events dispatched between BASIC statements. Movement events are coalesced and capped at about 200 handler calls per second. Mouse clicks fire on button-down edges. Handler line 0 disables the corresponding event. - Windows SCREEN width,height now accepts arbitrary logical framebuffer sizes from 8x16 through 8192x8192, subject to a 64-million-pixel safety cap. A window is scaled down when necessary to fit the monitor work area. F11 fullscreen preserves the BASIC aspect ratio and fills unused space with black bars rather than changing the desktop display mode. - UEFI SCREEN width,height continues to select an exact GOP resolution. Both platforms add SCREEN MODES, VIDEOMODES(), VIDEOMODE n,widthVar,heightVar and SCREEN MODE n. On Windows the enumerated list contains unique physical resolutions reported by the monitor containing the Thoreau window; selecting one changes the logical BASIC framebuffer, not the Windows desktop mode. On UEFI the list and selection map directly to GOP modes. - TCP/IPv4 networking is available through eight client slots (0..7). TCP OPEN, TCP SEND, TCP CLOSE and TCP TIMEOUT are joined by TCPRECV$(), TCPCONNECTED(), TCPEOF(), DNS$(), NETPRESENT(), NETERROR$(), HTTPGET$() and HTTPSTATUS(). NETINFO displays network backend, protocol availability, configuration and diagnostic state. HTTPGET$ accepts HTTP or HTTPS URLs and optional CR/LF-separated request headers, returning response bodies up to 1 MiB. Network failures are reported through NETERROR$ so ordinary connection failures do not have to abort a BASIC program. - Windows networking uses Winsock and WinHTTP. UEFI prefers the standard DNS4, TCP4 and HTTP service-binding protocols. If higher-level UEFI networking is missing or unusable but Simple Network Protocol is available, Thoreau can use its own raw-SNP Ethernet/ARP/DHCPv4/IPv4/UDP/DNS/TCP stack for DNS, TCP and plain HTTP. HTTPS remains on the firmware HTTP/TLS path. - INPUT accepts GW-BASIC's leading-semicolon form, for example INPUT ;"A=",A. The final Enter does not advance to the next text line. - NEXT accepts comma-separated loop variables, for example NEXT K,J,I, closing nested FOR loops in the listed order. - DEFxxx default typing now follows GW-BASIC variable identity. After DEFINT I-N, I and I% are the same variable. After DEFDBL R-T, R and R# are the same variable. Explicit suffixes of a different type remain distinct. VERSION 2.3.1 CHANGES ===================== Version 2.3.1 builds on 2.3 without changing existing program syntax: - IIF(condition,ifTrue,ifFalse) adds a conditional expression, particularly useful inside DEF FN definitions. The condition is evaluated first and only the selected result expression is evaluated. The unselected branch cannot cause an error or side effect. For example, IIF(X=0,0,1/X) is safe at zero. - Nested single-line IF/ELSE statements now follow the classic dangling-ELSE rule: ELSE binds to the nearest unmatched IF. A false outer IF skips the complete nested THEN clause, including any ELSE belonging to an inner IF. - IF branches that execute GOSUB now retain their enclosing single-line IF context across the subroutine call, so RETURN resumes at the correct ELSE or end of statement instead of producing a Syntax Error. - STOP reports its source line as "Break in n". CONT still resumes after the STOP, and the Machine Explorer records the last pause reason and location. - The Machine Explorer has live, read-only interpreter views: STATE summarizes execution and memory use, STACK displays GOSUB/timer returns, FLOW displays FOR/WHILE/handler/single-line-IF frames, BREAKS shows pause and breakpoint state, TIMERS shows programmable timers, and INTERNALS lists core structure addresses and capacities. - F12 enters DebuggerMode from a running program, INPUT, or the BASIC prompt. Entry clears the debugger screen, uses normal key repeat and temporarily hides sprites. X restores the exact framebuffer, text grid, cursor, colors, views, sprite presentation and prior KEYREPEAT settings, then resumes the program or returns to the prompt. THOREAU uses the same protected session. - LOAD, BREAK, CLEAR and NEW clears source-line breakpoints. - DIR and FILES display filenames, directory names and paths in uppercase, while retaining directories-first, case-insensitive sorting and [DIR] markers. - Windows keeps BASIC's current directory separate from the process current directory and opens ordinary files with delete-sharing. LOAD, RUN and LOADSPRITE close their source/asset handles promptly, so a game's directory may be renamed or deleted after loading unless it contains the running EXE. VERSION 2.3 CHANGES =================== Version 2.3 introduces sprites, game-loop timing controls and hypercomplex numbers: - Software sprites separate loaded images from instances. Up to 65,536 image slots and 65,536 instances are available, so many copies can share one bitmap in memory. Sprite dimensions may exceed the current screen and are clipped while drawing. - LOADSPRITE optionally defines a transparent color. A compact 1-bit opacity mask is generated at load time. SPRITECOLLIDE first rejects non-overlapping bounding boxes, then tests the common area for exact overlap of two non-transparent pixels. One opaque-pixel overlap is a collision. - SPRITE, MOVESPRITE, SHOWSPRITE, HIDESPRITE and DELSPRITE manage persistent sprite instances. SPRITEX and SPRITEY expose instance positions. - SPRITETEXT UNDER|OVER selects whether text ink is composited below or above software sprites. UNDER is the compatibility default; OVER is useful for score displays, HUDs and labels. - KEYREPEAT delay,rate provides game-style keyboard repeat timing on Windows and raw USB HID UEFI. KEYREPEAT DEFAULT restores normal platform behavior. Firmware-input UEFI fallback cannot override repeat because UEFI text input does not expose reliable key-release state. - WAITREL milliseconds provides relative frame pacing. Work done between calls counts toward the requested interval; late frames return immediately and re-anchor instead of producing a burst of catch-up frames. WAITREL 0 resets its timing reference. - The new @ numeric type adds complex numbers, quaternions and octonions as one hypercomplex promotion tower. CPLX, QUAT and OCT construct values. - @ values support +, -, *, /, = and <> with automatic promotion from real to complex to quaternion to octonion. Quaternion/octonion multiplication keeps its mathematical non-commutative behavior, and octonion multiplication is correctly non-associative. - CONJ, INV, NORM, NORM2, ABS and COMP operate on hypercomplex values. Named component access such as Z@.R, Z@.I, Q@.J and O@.E7 is supported, including component assignment. @ arrays are supported as ordinary BASIC arrays. - ^ accepts an @ base with an ordinary real scalar exponent. Integer powers use exponentiation by squaring; non-integer powers use the documented principal value EXP(exponent*LOG(base)). A@^B@ is intentionally rejected because quaternion multiplication is non-commutative and octonions add non-associativity, so there is no single unsurprising exponent convention. - SIN, COS, TAN, EXP, LOG, SQR/SQRT, SINH, COSH and TANH accept complex, quaternion and octonion @ values. LOG, SQRT and non-integer powers use a deterministic principal branch. Negative real quaternions choose +i; negative real octonions choose +e1. - ASCII LOAD and MERGE accept literal TAB characters (CHR$(9)) from external editors. Tabs are expanded to the next 4-column tab stop before the source line is stored, so LIST displays normal spaces rather than control glyphs. - Hypercomplex division, INV, ABS and NORM use scaled numerical algorithms to avoid avoidable overflow/underflow for very large or very small components. - Scalar and hypercomplex floating-point narrowing now reports Overflow rather than silently storing infinities where the BASIC type cannot represent the result. - Windows BLOAD/BSAVE use guarded memory access, so invalid process addresses become BASIC errors instead of crashing the interpreter. - SAVE and buffered PRINT# propagate disk write failures as Disk I/O error. - Apostrophe comments now terminate the token stream correctly after any statement element, including PRINT separators. For example: 10 PRINT "_"; ' Empty cell is accepted as expected. - WHILE now rejects trailing unparsed expression text instead of silently treating it as part of the loop structure. This catches mistakes such as WHILE NOR EOF(1) with a Syntax Error while still allowing NOR as an ordinary variable name. - DIR and FILES mark directories with [DIR], list directories before files, and sort names case-insensitively within each group. This also applies to wide directory listings. - Windows BLOAD and BSAVE validate memory accesses through Thoreau's guarded memory layer. UEFI deliberately retains raw bare-metal memory semantics. SAVE and buffered file output now propagate disk write failures as "Disk I/O error". VERSION 2.2 CHANGES =================== Version 2.2 collects compatibility, memory-management and usability fixes: - Strings are reclaimed automatically by a compacting garbage collector, so repeated concatenation and reassignment no longer steadily exhaust string space. - ERASE returns numeric/string-array descriptor blocks to a coalescing free list. Live arrays never move, so VARPTR addresses remain stable. - Loaded bitmaps use the same reusable arena. Replacing a LOADBMP slot returns the old pixel block, and failed loads release temporary allocations. - FRE(0) includes reusable reclaimed array/bitmap blocks instead of reporting only the untouched gap at the top of the arena. - SAVEBMP writes the active graphics VIEW, the full screen, or an explicit rectangle as an uncompressed 24-bit BMP. - BITBLT accepts both slot,x,y and slot,(x,y) destination syntax. - KILL accepts DOS-style * and ? wildcards. Matching is case-insensitive, non-recursive and never removes directories. - SAVE appends .BAS when the final path component has no extension. - Recursive DIR/FILES output can be aborted with ESC while traversal is in progress. - HELP uses the full physical text screen rather than an 80-column cap. It wraps at word boundaries and temporarily ignores TXTWINDOW and VIEW PRINT while the HELP interface is displayed. - INKEY$ returns classic Microsoft BASIC/DOS two-byte strings for supported extended keys on both Windows and UEFI: CHR$(0)+CHR$(scan). This includes the cursor/navigation keys and F1 through F10. PLATFORMS --------- Windows x64 - Native 64-bit Windows application. - BASIC program can be supplied as an autostart file. - COMMANDLINEARG$(n) exposes arguments passed to BASIC programs. - CREATEEXE creates a standalone Windows application. - SYSTEM closes Thoreau BASIC and exits the Windows process. x64 UEFI - Runs directly as an EFI application, with no operating system required. - Uses UEFI graphics and filesystem services. - STARTUP.BAS can automatically load and run at interpreter startup. - THOREAU.CFG beside the EFI can select an international keyboard layout. - KEYB can report or switch the active keyboard layout at runtime. - Compatible USB HID boot keyboards can be read directly; firmware input is used as a compatibility fallback when raw HID takeover is unavailable. The fallback keeps non-raw-HID keyboards usable but cannot provide independent key-up/repeat timing or recover keys the firmware does not expose. - CREATEEFI creates a standalone EFI application. - SYSTEM returns to the UEFI firmware/caller. - A generated EFI application can be used as \EFI\BOOT\BOOTX64.EFI on a suitable x64 UEFI boot volume. QUICK START ----------- 10 CLS 20 PRINT "HELLO FROM THOREAU BASIC" 30 FOR I=1 TO 5 40 PRINT I 50 NEXT I 60 END RUN Program files are plain ASCII BASIC source files. Literal TAB characters from external editors are accepted by LOAD and MERGE and expanded to 4-column tab stops before storage. Classic-style LOAD shorthand is supported: LOAD "GAME LOAD "GAME.BAS Both are valid. If LOAD is given a filename without an extension, .BAS is appended. The closing quote may be omitted for LOAD. RUN accepts a stored line number or a filename as well as the traditional bare form: RUN RUN 1000 RUN "GAME RUN "GAME.BAS" RUN with a filename uses LOAD semantics first. A missing extension defaults to .BAS, and the closing quote may be omitted just as with LOAD. Save a program (the .BAS extension is added when omitted): SAVE "GAME",A Create a standalone application after loading/editing the program: CREATEEXE "GAME" Windows -> GAME.EXE CREATEEFI "GAME" UEFI -> GAME.EFI THOREAU BASIC FEATURES NOT PRESENT IN GW-BASIC ============================================== The language intentionally resembles GW-BASIC, but Thoreau BASIC is not a byte-for-byte clone. These are major Thoreau additions or substantial extensions beyond GW-BASIC: 1. NATIVE 64-BIT WINDOWS AND BARE-METAL UEFI Thoreau BASIC runs as a native x64 Windows program and as an x64 EFI application directly under firmware, without DOS or another operating system. 2. CREATEEXE / CREATEEFI The currently loaded BASIC program can be packaged into a standalone Windows EXE or UEFI EFI application. CREATEEXE "MYGAME" CREATEEFI "MYGAME" 3. 64-BIT INTEGER TYPE The && suffix and DEFI64 provide signed 64-bit integers. A&&=9223372036854775807 DEFI64 A-Z 4. 64-BIT ADDRESS-ORIENTED BASIC VARPTR returns 64-bit addresses. LOMEM, HIMEM, FREEBOT, FREETOP and THOREAUADR expose the interpreter and machine memory layout. 5. WIDE PEEK/POKE PEEK16, PEEK32, PEEK64 and POKE16, POKE32, POKE64 complement byte PEEK/POKE. 6. THOREAU MACHINE EXPLORER THOREAU opens a built-in low-level machine monitor with memory dumps, searches, transfers, maps, landmarks and machine information. 7. STORAGE / BOOT ARCHAEOLOGY The Machine Explorer can inspect disks, sectors, partitions, filesystems, UEFI boot entries and perform best-effort installed-OS detection. Storage inspection commands are read-only. 8. 24-BIT GW-BASIC GRAPHICS EXTENSIONS Classic GW-BASIC-style PSET, PRESET, LINE, CIRCLE, PAINT, COLOR, POINT, GET/PUT, DRAW, VIEW and WINDOW operate on a 24-bit RGB framebuffer. Palette colors 0-15 remain compatible, while direct 0xRRGGBB values are accepted throughout. PSET/PRESET, LINE, PAINT and COLOR also accept r,g,b component triples. PSET (10,10),255,136,0 LINE (20,20)-(300,180),30,80,160,BF CIRCLE (320,240),100,&HFF8800 COLOR 255,255,255,16,16,16 POINT returns raw 24-bit RGB for non-palette pixels, and graphics GET/PUT preserve full 24-bit pixels. 9. BMP GRAPHICS LOADBMP loads uncompressed 24/32-bit BMP files into slots 0..65535, BITBLT draws them, and SAVEBMP writes the current graphics VIEW, full screen, or an explicit rectangle as a 24-bit BMP. BITBLT accepts either flat x,y coordinates or a GW-style (x,y) point and can use a transparent color key. LOADBMP 0,"ROOM.BMP" BITBLT 0,(0,0) BITBLT 0,(100,80),&HFF00FF SAVEBMP "SCREEN.BMP" 10. FRAMEBUFFER INTROSPECTION GRAMAXX, GRAMAXY, GRAPITCH and SCRNADR expose graphics dimensions and the framebuffer address. 11. EXTENDED SCREEN SELECTION SCREEN width,height selects by dimensions rather than the classic GW-BASIC mode-number model. Windows accepts arbitrary logical framebuffer sizes; UEFI selects exact GOP modes. SCREEN MODES, SCREEN MODE n, VIDEOMODES() and VIDEOMODE expose the physical/display mode list. 12. TXTWINDOW AND NAMED TEXT WINDOWS TXTWINDOW can set the default text rectangle and create named @n windows. PRINT @n, CLS @n and LOCATE @n can address those regions. 13. PRINT WRAP / PRINT JUSTIFY Long prose can be word-wrapped or fully justified directly by PRINT. PRINT WRAP 60,TEXT$ PRINT JUSTIFY 60,TEXT$ 14. MULTIPLE PROGRAMMABLE TIMERS Eight independent millisecond timers (0..7) can call GOSUB handlers. 15. BREAKPOINT MANAGER BREAK can set, list, delete and clear source-line breakpoints. BREAK 1000,2000 BREAK LIST BREAK DELETE 1000 BREAK CLEAR 16. VARIABLE WATCHING AND INTROSPECTION TRACE can watch scalar values while the program runs. VARINFO and ARRAYINFO can list variables, arrays, types, sizes, values and addresses. 17. SOURCE DEVELOPMENT TOOLS FIND supports ranges, WORD matching and FIND NEXT/PREV. REPLACE can perform literal replacement or safe identifier renaming. XREF finds symbol and line references, AUDIT checks common structural/source mistakes, and PROFILE measures executed lines. FIND "LOADBMP",1000-5000 FIND "PLAYERX",WORD FIND NEXT REPLACE "PLAYERX","SHIPX",WORD XREF SCORE AUDIT PROFILE ON PROFILE ON MARK 18. EXTENDED LIST / EDIT ERROR WORKFLOW LIST ERL and EDIT ERL jump directly to the last stored-program error line. LIST also supports paging and NOWAIT. 19. RECURSIVE / WIDE / PAGED DIRECTORY LISTING DIR is an alias for FILES and S, W and P options add recursion, wide output and paging. DIR "*.BAS",S,W,P 20. LCASE$ / UCASE$ ASCII case conversion functions are provided. 21. PLATFORM STARTUP / ARGUMENT FEATURES Windows provides COMMANDLINEARG$(n). The UEFI interpreter supports STARTUP.BAS and THOREAU.CFG. 22. SAFE WINDOWS MEMORY ACCESS Arbitrary PEEK/POKE-style access on Windows is guarded so invalid or protected addresses become BASIC errors instead of simply crashing the interpreter. 23. CATEGORIZED BUILT-IN HELP HELP and HELP name provide a built-in reference for the language and extensions. HELP uses the full physical text screen, wraps descriptions at word boundaries, and is independent of TXTWINDOW / VIEW PRINT while shown. 24. ON BREAK GOTO ESC/break events can be routed to a BASIC handler and resumed using the normal RESUME machinery. 25. LARGE MODERN BASIC MEMORY ARENA Variables, arrays, strings and loaded bitmaps use a modern 64-bit memory arena rather than the tiny segmented memory model of DOS BASIC. Strings are compacted automatically; ERASE and replaced bitmap slots return storage to a coalescing free list. Live arrays do not move, preserving VARPTR values, and FRE(0) includes reusable reclaimed blocks. 26. INTERNATIONAL UEFI KEYBOARD SUPPORT The UEFI build supports 23 DOS-style keyboard layout codes through THOREAU.CFG and the runtime KEYB command. Compatible USB HID boot keyboards can be read directly, bypassing incomplete firmware key translation. 27. HYPERCOMPLEX NUMBERS The @ suffix adds a native hypercomplex numeric type covering complex numbers, quaternions and octonions. Values participate directly in +, -, *, /, ^, = and <> expressions, may be stored in arrays, expose named components, and support transcendental functions including EXP, LOG, SIN, COS, TAN, SINH, COSH, TANH and principal square roots. Z@=CPLX(3,4) Q@=QUAT(1,2,3,4) O@=OCT(1,2,3,4,5,6,7,8) 28. MOUSE INPUT AND EVENTS Windows and UEFI share mouse position/button/wheel functions, MOUSE ON/OFF, MOUSEPOS and ON MOUSEMOVE / ON MOUSECLICK GOSUB handlers. UEFI provides its own software pointer over the framebuffer when a firmware pointer protocol is available. 29. SIMULTANEOUS HELD-KEY STATE KEYDOWN(key$) lets games test several currently held controls in one frame without consuming the INKEY$ event queue. KEYSTATEAVAILABLE tells portable programs whether the current keyboard backend can report key releases. 30. TCP/IP, DNS AND HTTP/HTTPS Eight TCP/IPv4 client slots, DNS lookup and HTTPGET$ provide ordinary BASIC access to network services on Windows and UEFI. NETINFO reports network backend, protocol availability, addressing and diagnostic state. On UEFI, a raw SNP fallback can supply Ethernet, ARP, DHCPv4, IPv4, UDP, DNS, TCP and plain HTTP when higher-level firmware network protocols are unavailable. 31. NATIVE x64 BYTECODE / JIT EXECUTION Stored BASIC programs can compile supported expressions, statements, loops and cross-line regions to native x64 code. The JIT covers ordinary scalar numeric work, native hypercomplex values, numeric/@ arrays, IF/ELSE, FOR/NEXT, WHILE/WEND, DEF FN and classic GOSUB/RETURN-heavy code. Unsupported constructs automatically fall back to the interpreter. JIT OFF provides a complete classic-interpreter path for compatibility and A/B testing. INCLUDED SHOWCASE PROGRAMS -------------------------- The included examples exercise Thoreau's newer facilities rather than only document their syntax. SpriteInvaders A compact Space-Invaders-style sprite demonstration. It shows loaded sprite images, multiple persistent instances, movement, transparent sprites, collision detection, projectiles, keyboard control and timed game loops. NeonDescent A more ambitious 1024x768 scrolling shooter inspired by classic vertically scrolling PC/Amiga shooters. A large bitmap is scrolled with BITBLT while ships, aliens, shots and bombs are handled by the sprite system. It demonstrates many simultaneous sprite instances, pixel-perfect collisions, HUD text over sprites, KEYREPEAT, WAITREL and continuous background motion. GorseGlass A 1024x768 analytic raytracer used as both a visual demo and a JIT stress test. It combines nested pixel loops, arrays, many GOSUB/RETURN calls, hard shadows, a checkerboard floor, reflective materials and a glass sphere with explicit entry/exit Snell refraction plus Schlick Fresnel blending. The included v2.5 file is the quality version retained after comparison against the faster simplified secondary-shading path. Island3D A first-person fractal-island renderer and PARFOR stress test. The distributed configuration renders a 640x480 view over a 1024x1024 heightfield (VOX=4) with shoreline shaping, distance fog, directional terrain lighting, trees and a double-buffered column renderer. Each screen column is an independent PARFOR iteration and writes to its own slice of the work buffer before one completed frame is presented with PUT. Start it with: RUN "ISLAND3D" Running controls are mouse-only, so the demo does not depend on USB HID KEYDOWN support once it has started: move mouse look / turn hold left button walk forward hold right button walk backward hold both buttons quit A mouse is required; the program checks MOUSEPRESENT before entering the main loop. OPTION PARTHREADS 0 lets Thoreau choose the worker count. Terrain density is controlled near the top of the program by VOX. The supplied VOX=4 gives a 1024x1024 heightfield; VOX=2 gives 512x512 and reduces ray-sampling density accordingly. The frame limiter is intentionally disabled for benchmarking: REM CAP=1 Remove REM from that line to enable the WAITREL 16 limiter. Leave it commented to see the uncapped FPS counter. complex-demo A 2D Mandelbrot renderer written using the new native complex syntax. Instead of manually carrying separate real and imaginary variables, the iteration can be written directly with @ values: C@=CPLX(CR,CI) Z@=CPLX(0,0) Z@=Z@*Z@+C@ The demo is a compact introduction to CPLX(), @ variables and complex arithmetic inside an ordinary BASIC graphics program. quaternion-demo A quaternion fractal demonstration using the 4-component QUAT() syntax. It renders a three-dimensional ray-marched slice of a four-dimensional quaternion Julia set, using iterations such as: Q@=QUAT(X,Y,Z,W) Q@=Q@*Q@+C@ The program combines quaternion arithmetic, NORM, LOG, ray marching, numerical surface normals and 24-bit graphics. It is deliberately a substantial example of the new mathematics rather than a syntax test. mouse-paint-demo A compact paint program using mouse position, buttons, wheel-controlled brush sizing and ON MOUSEMOVE / ON MOUSECLICK event handlers. video-modes-demo Enumerates physical/display modes with VIDEOMODES and VIDEOMODE and shows how SCREEN MODE selects one. iss-tracker A HTTP networking example. It reads the current International Space Station position from a public API and plots it on WORLDMAP.BMP, leaving an orbital trail behind the moving position. DATA TYPES ---------- Suffix Type ------ ---- % 16-bit integer & 32-bit integer && 64-bit integer ! single-precision floating point # double-precision floating point $ string @ hypercomplex (complex / quaternion / octonion) DEFI64 adds a native 64-bit integer default type. Integer literals and memory addresses can use the full 64-bit range supported by the interpreter. DEFINT, DEFLNG, DEFI64, DEFSNG, DEFDBL and DEFSTR also determine the resolved type of an unsuffixed name. When the resolved type matches an explicit suffix, the two spellings are aliases for the same variable, as in GW-BASIC: DEFINT I-N : I=42 : PRINT I% DEFDBL R-T : R#=3.5 : PRINT R A suffix that explicitly requests another type still creates a distinct name. HYPERCOMPLEX NUMBERS -------------------- Thoreau BASIC treats complex numbers, quaternions and octonions as one native @ type. The value carries its current dimension internally: complex 2 components real, i quaternion 4 components real, i, j, k octonion 8 components real, e1, e2, e3, e4, e5, e6, e7 Constructors: Z@=CPLX(3,4) Q@=QUAT(1,2,3,4) O@=OCT(1,2,3,4,5,6,7,8) A plain real number mixed with an @ value is promoted automatically. Promotion follows the Cayley-Dickson tower: real -> complex -> quaternion -> octonion The wider operand determines the result dimension. For example: Z@=CPLX(10,20) Q@=QUAT(1,2,3,4) PRINT Q@+Z@ The complex value is embedded as (10,20,0,0) before quaternion addition. Assigning an ordinary real number to an @ variable creates a complex value with zero imaginary part: A@=5 ' equivalent to CPLX(5,0) @ arrays are ordinary BASIC arrays: DIM Z@(100) DIM Q@(20,20) Z@(10)=CPLX(2,3) COMPONENT ACCESS Named components may be read directly: Z@.R real component Z@.I complex i Q@.R Q@.I Q@.J Q@.K O@.R O@.E1 O@.E2 ... O@.E7 For convenience, .I is the same component as .E1, .J as .E2, and .K as .E3. Array elements and parenthesized hypercomplex expressions may also use the postfix: PRINT Q@(5).K PRINT (A@*B@).E7 PRINT CONJ(Q@).I Reading a component above the value's current dimension returns zero. Assigning such a component promotes the value automatically: A@=CPLX(1,2) A@.K=3 A@ is now a quaternion, equivalent to QUAT(1,2,0,3). COMP(x,n) is the expression-friendly alternative and returns component 0..7. Component 0 is always the real/scalar component: PRINT COMP(A@*B@,3) ARITHMETIC The operators +, -, * and / work directly on @ values. Addition/subtraction are componentwise. Multiplication uses the standard Cayley-Dickson construction with the quaternion convention: i*j = k j*k = i k*i = j Quaternion multiplication is not commutative: I@=QUAT(0,1,0,0) J@=QUAT(0,0,1,0) PRINT I@*J@ ' +k PRINT J@*I@ ' -k Octonion multiplication is neither commutative nor associative. Thoreau uses the language's normal left-associative evaluation, so: A@*B@*C@ means: (A@*B@)*C@ For octonions, A@*(B@*C@) may genuinely produce a different result. This is a property of octonion algebra, not a rounding or parser error. Division is defined explicitly as: A@ / B@ = A@ * INV(B@) Division by a zero-norm value reports Division by zero. FUNCTIONS CONJ(x) conjugate; negate every non-real component INV(x) multiplicative inverse ABS(x) Euclidean magnitude NORM(x) Euclidean magnitude; same result as ABS for @ values NORM2(x) squared Euclidean norm COMP(x,n) component 0..7 Examples: Z@=CPLX(3,4) PRINT ABS(Z@) ' 5 PRINT NORM2(Z@) ' 25 PRINT CONJ(Z@) PRINT Z@*INV(Z@) ' unit value COMPARISON AND OUTPUT = and <> compare all promoted components exactly. Hypercomplex values have no natural ordering, so <, >, <= and >= report Illegal comparison. PRINT and STR$ use a canonical component form and keep the current dimension visible, for example: 3+4i 1+2i+3j+4k 1+2e1+3e2+4e3+5e4+6e5+7e6+8e7 Every component is printed, including zero components. Hypercomplex values are stored internally with double-precision components. TRANSCENDENTAL FUNCTIONS AND POWERS The one-value functions EXP, LOG, SIN, COS, TAN, SINH, COSH, TANH and square root work on complex numbers, quaternions and octonions. SQR and SQRT are equivalent square-root spellings. Ordinary scalar arguments continue to use their traditional real-number behavior. For an @ value x, write x = a + v where a is the real component and v is the vector formed by all non-real components. Let r=|v|. When r is nonzero, u=v/r is the unit imaginary direction carried by x itself. Because the subalgebra generated by one complex/quaternion/octonion value is associative, the same closed forms work for all three dimensions. In particular: EXP(a+v) = exp(a) * (cos(r) + u*sin(r)) SIN(a+v) = sin(a)*cosh(r) + u*cos(a)*sinh(r) COS(a+v) = cos(a)*cosh(r) - u*sin(a)*sinh(r) SINH(a+v) = sinh(a)*cos(r) + u*cosh(a)*sin(r) COSH(a+v) = cosh(a)*cos(r) + u*sinh(a)*sin(r) TAN(x) is SIN(x)/COS(x), and TANH(x) is SINH(x)/COSH(x). A zero denominator reports Division by zero. Large real or vector components can overflow the underlying double-precision exponential/hyperbolic calculations; Thoreau reports Overflow rather than silently returning an invalid @ value. LOG AND PRINCIPAL VALUES LOG is multivalued for complex numbers and even more so for quaternions and octonions. Thoreau therefore defines one deterministic principal value. For a non-real x=a+v: LOG(x) = log(|x|) + u*atan2(|v|,a) For positive real @ values the imaginary part is zero. For a negative real complex value the principal direction is +i, matching the usual complex principal logarithm. A negative real quaternion also chooses +i, while a negative real octonion chooses +e1. These are conventions: infinitely many other quaternion/octonion logarithms are mathematically valid. LOG of a zero @ value, for example LOG(CPLX(0,0)), reports Illegal function call. The same convention determines principal square roots: SQRT(x) = SQR(x) = EXP(.5*LOG(x)) with zero handled directly. Thus: PRINT SQRT(CPLX(-1,0)) PRINT SQRT(QUAT(-1,0,0,0)) PRINT SQRT(OCT(-1,0,0,0,0,0,0,0)) select +i for the complex/quaternion results and +e1 for the octonion result. Other roots exist; Thoreau deliberately returns one repeatable principal root. POWER OPERATOR The exponent of an @ value must be an ordinary real scalar: Q@^2 Q@^-3 O@^.5 Integer exponents are evaluated by exponentiation by squaring. This is unambiguous even for octonions because the Cayley-Dickson algebras used here are power-associative: powers of one value have a well-defined meaning. Negative integer exponents use INV(x). Non-integer real powers use the principal definition: x^p = EXP(p*LOG(x)) so they inherit the LOG branch convention described above. Zero to a positive real power is zero; zero to a negative power reports Division by zero. A hypercomplex exponent is intentionally not accepted: A@^B@ ' Type mismatch For quaternions, EXP(B@*LOG(A@)) and EXP(LOG(A@)*B@) need not agree because multiplication is non-commutative. Octonions additionally make parenthesization significant. Thoreau does not choose one of those inequivalent definitions silently. IDENTITIES AND QUIRKS Functions of a single @ value are well defined under the rules above, but many familiar multi-value identities require commuting operands. For example, with independent quaternion or octonion values A@ and B@, users must not generally assume: EXP(A@+B@) = EXP(A@)*EXP(B@) or ordinary trigonometric addition formulas. Octonion multiplication remains non-associative, so explicit parentheses can change expressions involving several independently oriented values. This is mathematical behavior, not an interpreter quirk. Examples: Z@=CPLX(0,1) PRINT EXP(Z@) PRINT SIN(Z@) PRINT COS(Z@) Q@=QUAT(1,2,3,4) PRINT EXP(LOG(Q@)) PRINT Q@^2 PRINT Q@^.5 O@=OCT(-1,0,0,0,0,0,0,0) PRINT SQRT(O@) ' principal +e1 root WRITE#/INPUT# do not define a portable textual @ serialization; use STR$ or store components explicitly when a file representation is needed. ERROR HANDLING -------------- ON ERROR GOTO 9000 ... 9000 PRINT "ERROR";ERR;"AT";ERL 9010 RESUME NEXT Runtime errors print their message and source line, for example: Illegal function call in 1230 ON BREAK GOTO can trap ESC/break events. RESUME, RESUME NEXT and RESUME line leave an active error/break handler correctly. PROGRAMMABLE TIMERS ------------------- Eight independent timers are available, numbered 0 through 7. TIMER(0)=1000 ON TIMER(0) GOSUB 9000 TIMER(0) ON Intervals are milliseconds. Timers are non-preemptive and are dispatched between BASIC statements. RELATIVE FRAME PACING --------------------- WAITREL is intended for game loops, animation and other code that needs a stable frame period without manually subtracting TIMER values: WAITREL milliseconds The first WAITREL establishes the reference point and waits the requested interval. Later calls wait only for the time still remaining since the previous WAITREL returned. Code executed between calls therefore counts toward the interval. For example: 100 GOSUB 1000 110 WAITREL 16 120 GOTO 100 If the game logic in GOSUB 1000 takes 5 ms, WAITREL waits roughly another 11 ms. If a frame already took 20 ms, WAITREL 16 returns immediately and re-anchors to the current time. It deliberately does not generate catch-up frames. WAITREL 0 can be used to reset the reference without a delay. WAITREL uses the platform's monotonic high-resolution timing. On modern Windows it uses a high-resolution waitable timer when available; on older Windows it yields while waiting rather than inheriting the coarse desktop Sleep() interval. On UEFI it uses short firmware Stall() intervals. ESC and ON BREAK GOTO remain responsive while WAITREL is waiting. UEFI INTERNATIONAL KEYBOARD SUPPORT =================================== This section applies only to the x64 UEFI build. Windows uses the normal Windows keyboard input and does not use THOREAU.CFG or KEYB layout translation. At startup, Thoreau looks for THOREAU.CFG in the directory containing the EFI. A keyboard layout is selected with a DOS-style line such as: KEYB GR If THOREAU.CFG is absent, the default is US. Blank lines and lines beginning with ;, # or REM are ignored. An unknown KEYB code falls back to US at startup. The active layout can be displayed or changed immediately from BASIC: KEYB KEYB GR KEYB UK KEYB US A runtime KEYB change affects only the current session and does not rewrite THOREAU.CFG. An unknown runtime code leaves the current layout unchanged. Supported layouts: Code Layout Code page ---- ----------------------------- --------- BE Belgium 850 BR Brazil 850 DK Denmark 850 GR Germany 850 SU Finland 850 FR France 850 UK United Kingdom 850 IT Italy 850 YU Yugoslavia 852 CF Canadian French 850 LA Latin America 850 NL Netherlands 850 NO Norway 850 PL Poland 852 PO Portugal 850 SV Sweden 850 SG Swiss German 850 SF Swiss French 850 SP Spain 850 SL Slovak 852 CZ Czech 852 HU Hungary 852 US USA 437 On a compatible USB HID boot keyboard, Thoreau can read raw HID reports and translate physical key usages itself. This avoids firmware errors involving international keys, including the ISO 102nd key used for <, > and | on several European layouts. Raw USB HID is preferred, but it cannot be assumed on every UEFI machine. An internal laptop keyboard, PS/2-style keyboard, Bluetooth keyboard, firmware- managed keyboard controller, or a USB keyboard whose EFI_USB_IO_PROTOCOL device cannot be safely taken over may be available only through the generic UEFI text input interface. Rather than make Thoreau unusable on such systems, it falls back to firmware keyboard input. The active backend is shown at startup. Typical status lines are: Keyboard: GR (CP850, USB HID) Keyboard: GR (CP850, firmware) The difference has practical consequences. Raw USB HID exposes physical key usages and key-release state, so Thoreau can distinguish international physical keys accurately, apply its own KEYB layout translation and implement independent KEYREPEAT timing. Firmware input has already been interpreted by the firmware and does not provide reliable key-release events. Thoreau can still apply the selected layout as far as the received key information allows, but it cannot recover a physical key the firmware never reports. In particular, a firmware that collapses or omits the ISO 102nd key cannot be repaired by software above that interface. For the same reason, KEYREPEAT delay/rate control is available on raw USB HID UEFI input but not on firmware fallback. In firmware mode the firmware owns repeat timing. The fallback is therefore a compatibility path, not the preferred keyboard backend: it keeps more machines usable at the cost of less complete physical-key information and no independent key-up/repeat control. INKEY$ EXTENDED KEYS ==================== This section applies to both Windows and UEFI. INKEY$ returns an empty string when no key is waiting and a one-character string for ordinary character keys. Supported extended keys use the classic Microsoft BASIC/DOS two-byte form: CHR$(0)+CHR$(scan) The scan values are: Key Scan Key Scan --------- ---- --------- ---- F1 59 F6 64 F2 60 F7 65 F3 61 F8 66 F4 62 F9 67 F5 63 F10 68 Home 71 Up 72 Page Up 73 Left 75 Right 77 End 79 Down 80 Page Down 81 Insert 82 Delete 83 For example: K$=INKEY$ IF K$=CHR$(0)+CHR$(72) THEN PRINT "UP" IF K$=CHR$(0)+CHR$(80) THEN PRINT "DOWN" IF K$=CHR$(0)+CHR$(75) THEN PRINT "LEFT" IF K$=CHR$(0)+CHR$(77) THEN PRINT "RIGHT" This makes old BASIC games that test DOS/GW-BASIC extended-key strings portable between the Windows and UEFI builds. KEY REPEAT FOR GAMES ==================== KEYREPEAT can override the usual typematic delay: KEYREPEAT delayMilliseconds,rateHz KEYREPEAT DEFAULT For example: KEYREPEAT 0,30 The initial key press is delivered immediately. With a delay of 0, the first repeat follows after one normal repeat interval, so 0,30 feels continuous for game movement instead of waiting through the desktop keyboard-repeat delay. On Windows, custom KEYREPEAT timing is generated by Thoreau from key-down and key-up state and does not depend on the Windows user repeat setting. DEFAULT returns control to the normal Windows typematic setting. On UEFI with direct raw USB HID keyboard input, Thoreau also has key-up state and uses the requested timing. The UEFI firmware text-input fallback does not expose key-up state, so firmware repeat timing cannot be overridden there. KEYREPEAT DEFAULT restores the raw-HID default of approximately 500 ms at 30 repeats per second. SIMULTANEOUS KEY STATE ---------------------- INKEY$ remains the classic nonblocking key-event queue. For action games, 2.4 also provides held-state queries that do not remove anything from that queue: IF KEYDOWN("LEFT") THEN X=X-4 IF KEYDOWN("RIGHT") THEN X=X+4 IF KEYDOWN("SPACE") THEN GOSUB 9000 All three tests are independent, so LEFT+SPACE can move and fire in one frame. KEYDOWN accepts single characters, common names such as LEFT, RIGHT, UP, DOWN, SPACE, ENTER, ESC, SHIFT, CTRL, ALT and F1..F12, and classic two-byte extended keys such as CHR$(0)+CHR$(75). KEYSTATEAVAILABLE KEYSTATEAVAILABLE() returns -1 when real held-key state is available. Windows provides it while the Thoreau window is active. On UEFI it requires the raw USB HID backend, whose boot-keyboard report can represent up to six ordinary simultaneous keys plus modifier keys. Firmware text input has no reliable key-release information, so KEYSTATEAVAILABLE returns 0 there. When RUN or CONT returns to Ready, version 2.5.2 discards queued gameplay key events and interpreter-owned repeat state on both platforms. This does not change KEYDOWN while the program is running; it prevents old movement/fire keys from being consumed later by the editor, INKEY$, INPUT$ or LIST paging. MOUSE INPUT AND EVENTS ---------------------- Mouse state uses physical framebuffer coordinates on both platforms: MOUSE ON MOUSEPOS 320,240 X=MOUSEX() Y=MOUSEY() B=MOUSEB() W=MOUSEWHEEL() PRINT MOUSEPRESENT MOUSEB uses bit 0 for left, bit 1 for right and bit 2 for middle where the platform exposes it. MOUSEWHEEL is cumulative and signed. MOUSE ON/OFF controls pointer visibility; state functions remain safe if no mouse is present. Windows uses the native window pointer and translates scaled/letterboxed window coordinates back to BASIC framebuffer coordinates. UEFI prefers EFI_SIMPLE_POINTER_PROTOCOL and falls back to EFI_ABSOLUTE_POINTER_PROTOCOL. It draws a 12x18 black/white pointer after the BASIC framebuffer and sprite layers, so pointer movement does not burn trails into program graphics. Mouse events use ordinary non-preemptive GOSUB handlers: ON MOUSEMOVE GOSUB 9000 ON MOUSECLICK GOSUB 9100 They dispatch between BASIC statements, like programmable timers. Movement is coalesced and dispatched at up to about 200 Hz. MOUSECLICK fires on a button-down edge. A handler line of 0 disables the event. On UEFI pointer protocols are polled on a roughly 5 ms cadence while a program is running. VIDEO MODES AND LOGICAL FRAMEBUFFERS ------------------------------------ Windows and UEFI expose the same discovery syntax: SCREEN MODES N=VIDEOMODES() VIDEOMODE index,widthVar,heightVar SCREEN MODE index On UEFI these are real GOP modes. SCREEN width,height finds an exact matching GOP resolution, and SCREEN MODE selects the indexed GOP mode. Windows uses a logical BASIC framebuffer instead of switching the Windows desktop mode. SCREEN width,height accepts arbitrary sane raster sizes from 8x16 through 8192x8192, with a 64-million-pixel cap. If the requested framebuffer is larger than the available work area, the window is scaled down while preserving aspect ratio. F11 fullscreen scales the same framebuffer to the monitor and uses black bars for unused space. VIDEOMODES returns the unique physical resolutions reported by the monitor containing the Thoreau window; SCREEN MODE uses one of those dimensions for the logical framebuffer. TCP/IP, DNS AND HTTP/HTTPS -------------------------- Thoreau 2.4 provides a common IPv4 client API on Windows and UEFI. Eight TCP slots are available, numbered 0 through 7: TCP OPEN 0,"example.com",80 TCP SEND 0,"GET / HTTP/1.0"+CHR$(13)+CHR$(10)+CHR$(13)+CHR$(10) A$=TCPRECV$(0) TCP CLOSE 0 TCP TIMEOUT 15000 PRINT TCPCONNECTED(0) PRINT TCPEOF(0) PRINT DNS$("example.com") PRINT NETPRESENT() NETINFO NETINFO is a diagnostic command. It displays the active network backend and the most recent network error. On UEFI it also reports availability of SNP, PXE, Managed Network, DHCP4, IP4, UDP4, DNS4, TCP4, HTTP and TLS; raw-SNP readiness; and the current IP address, subnet mask, gateway and DNS server when known. This is useful both for programs being developed against the network API and for diagnosing firmware whose high-level network services are incomplete. HTTP and HTTPS requests are available without manually constructing HTTP text: J$=HTTPGET$("https://example.com/") PRINT HTTPSTATUS() PRINT NETERROR$() Optional request headers are supplied as CR/LF-separated Name: value lines: H$="Accept: application/json"+CHR$(13)+CHR$(10) J$=HTTPGET$(URL$,H$) HTTPGET$ returns the response body and accepts bodies up to 1 MiB. Ordinary network failures do not raise a BASIC runtime error; the call returns an empty result where appropriate and NETERROR$ describes the most recent network error. Syntax/type errors remain normal BASIC errors. Windows implements raw networking with Winsock and HTTP/HTTPS with WinHTTP. UEFI first uses the standard EFI_DNS4_PROTOCOL, EFI_TCP4_PROTOCOL and EFI_HTTP_PROTOCOL service bindings where they work. If those higher-level services are absent or unusable but EFI_SIMPLE_NETWORK_PROTOCOL is available, Thoreau can fall back to its internal raw network stack: Ethernet -> ARP -> DHCPv4 -> IPv4 -> UDP -> DNS -> TCP -> plain HTTP The raw path acquires IPv4 configuration with DHCPv4 and supplies the DNS and TCP operations used by the common BASIC API. HTTPS is not implemented by the raw stack; it continues to depend on the firmware HTTP/TLS implementation. NETINFO shows which firmware protocols were found, whether raw SNP is ready, the active backend, current IP/subnet/gateway/DNS values and the last network error. Network features remain optional on UEFI; NETPRESENT() can be used before a program assumes that a usable IPv4 stack is available. NUMERIC LITERALS ================ Decimal numbers use the normal BASIC forms. Thoreau also accepts classic Microsoft BASIC hexadecimal and octal prefixes anywhere a numeric literal is valid: &HFF hexadecimal 255 &O377 octal 255 &O10 octal 8 The H and O prefixes are case-insensitive. 24-BIT GW-BASIC GRAPHICS ======================== Thoreau BASIC keeps the classic GW-BASIC graphics model, but the drawing surface is a modern 24-bit RGB framebuffer. COLOR VALUES ------------ Most graphics commands accept the traditional palette numbers 0 through 15. Those map to the 16 CGA-style colors. They also accept a packed 24-bit RGB value: &HRRGGBB Examples: &HFF0000 red &H00FF00 green &H0000FF blue &HFF8800 orange &H202020 dark gray Internally the low 24 bits are used as 0xRRGGBB. A non-negative color value greater than 15 is interpreted as a direct RGB color. Several commands also accept three separate RGB components, each 0 through 255: red,green,blue For example, these two commands draw the same color: PSET (100,100),&HFF8800 PSET (100,100),255,136,0 PSET / PRESET ------------- Classic forms: PSET [STEP](x,y)[,color] PRESET [STEP](x,y)[,color] Thoreau 24-bit forms: PSET [STEP](x,y),r,g,b PRESET [STEP](x,y),r,g,b Examples: PSET (100,80),&H40C0FF PSET (100,80),64,192,255 PRESET STEP(10,0),255,0,0 If the color is omitted, PSET uses the current foreground color and PRESET uses the current background color. Both update the GW-BASIC "last point referenced", so STEP coordinates and LINE -(x,y) retain classic behavior. LINE ---- Classic geometry and B/BF box flags are retained: LINE [[STEP](x1,y1)]-[STEP](x2,y2)[,color][,B|BF] The color may be a palette number, a packed 24-bit value, or an RGB triple: LINE (10,10)-(300,150),&HFF8800 LINE (10,10)-(300,150),255,136,0 LINE (10,10)-(300,150),255,136,0,B LINE (10,10)-(300,150),30,80,160,BF B draws a box and BF draws a filled box. If the first point is omitted, LINE starts from the last point referenced: PSET (20,20) LINE -(200,100),&H00FF80 STEP on the second point is relative to the first point of that LINE. CIRCLE ------ CIRCLE [STEP](x,y),radius[,color[,start[,end[,aspect]]]] CIRCLE accepts a palette color or one packed 24-bit RGB value: CIRCLE (320,240),100,&HFF8800 The GW-BASIC start, end and aspect arguments are accepted by the parser so older source continues to load, but in Thoreau BASIC 2.3 they are currently ignored. CIRCLE therefore draws a complete circle rather than arcs or ellipses. PAINT ----- PAINT [STEP](x,y)[,paint[,border]] The paint color accepts a palette/direct color or an RGB triple: PAINT (100,100),&H204080 PAINT (100,100),32,64,128 An optional border color follows. The border is one palette/direct packed color value: PAINT (100,100),32,64,128,&HFFFFFF The fill is a four-connected scanline flood fill. If border is omitted, the paint color is also used as the border color, matching the GW-BASIC default. POLYFILL -------- POLYFILL (x1,y1),(x2,y2),(x3,y3)[,...][,color] POLYFILL (x1,y1),(x2,y2),(x3,y3)[,...],r,g,b POLYFILL fills a polygon directly using the even-odd scanline rule. Concave polygons are supported, and up to 4096 vertices may be supplied. STEP on a vertex makes it relative to the preceding vertex. The color accepts palette values, packed 24-bit RGB, or separate RGB components. If color is omitted, the current foreground color is used. Examples: POLYFILL (20,20),(180,40),(130,160),(40,120),&HFF8800 POLYFILL (20,20),(180,40),(130,160),(40,120),255,136,0 COLOR ----- COLOR controls the current foreground/background colors used by text and by graphics commands whose color is omitted. Traditional forms: COLOR fg COLOR fg,bg COLOR ,bg Both fg and bg may be palette numbers or packed 24-bit colors: COLOR &H80FF40,&H101810 Thoreau also accepts RGB triples: COLOR r,g,b COLOR r,g,b,background_r,background_g,background_b Examples: COLOR 255,136,0 COLOR 255,136,0,16,16,16 Named text windows can have their own colors: COLOR @1,255,255,0,0,0,64 POINT ----- POINT(x,y) POINT reads the framebuffer pixel. For compatibility, if the pixel exactly matches one of the 16 standard palette entries, POINT returns the palette index 0 through 15. Otherwise it returns the raw packed 24-bit RGB value. Example: PSET (10,10),255,136,0 PRINT HEX$(POINT(10,10)) prints: FF8800 POINT returns -1 outside the screen or outside the active graphics VIEW. GET / PUT --------- The classic sprite/image commands operate on full 24-bit pixels: GET [STEP](x1,y1)-[STEP](x2,y2),array PUT [STEP](x,y),array[,PSET|PRESET|XOR|AND|OR] GET stores an 8-byte width/height header followed by one 32-bit value per pixel; the low 24 bits contain 0xRRGGBB. The numeric array must therefore provide at least: 8 + 4 * width * height bytes of storage. Example for a 64x64 image using a LONG array and OPTION BASE 0: OPTION BASE 0 DIM SPR&(4097) GET (0,0)-(63,63),SPR& PUT (200,100),SPR&,PSET PUT supports PSET, PRESET, XOR, AND and OR. XOR is the default, as in GW-BASIC. All operations are masked to 24 bits. GET and PUT require the entire rectangle to fit on screen; an out-of-bounds rectangle raises Illegal function call. PSET, LINE, CIRCLE and PAINT instead clip silently at the screen/VIEW boundary. DRAW ---- Thoreau implements the GW-BASIC Graphics Macro Language commands: U D L R E F G H M B N A TA C S P Ppaint,border flood-fills at the current DRAW position using the same engine as PAINT. Both values use DRAW numeric syntax, including =variable; substitution. The C command uses the same color resolver as the other graphics commands: 0 through 15 are palette colors, while larger values are packed RGB. Inside DRAW strings, numeric values are decimal or may be taken from a BASIC variable with =name; syntax. This is convenient for hexadecimal RGB values: COL&&=&HFF8800 DRAW "C=COL&&;R80D40L80U40" WINDOW / VIEW / SCREEN ---------------------- GW-BASIC logical graphics coordinates are supported: WINDOW (x1,y1)-(x2,y2) WINDOW SCREEN (x1,y1)-(x2,y2) Without SCREEN, Y increases upward in logical coordinates. With SCREEN, Y increases downward. WINDOW affects coordinate mapping; it is not a display page selector. VIEW defines a physical graphics clipping rectangle: VIEW [SCREEN] (x1,y1)-(x2,y2)[,fill[,border]] VIEW fill and border accept palette numbers or packed 24-bit colors: VIEW SCREEN (0,0)-(639,479),&H101820,&HFFFFFF SCREEN selects a graphics mode by dimensions rather than by an old DOS mode number: SCREEN 640,480 SCREEN 800,600 SCREEN 1024,768 The requested dimensions must correspond to a mode supported by the platform. BITMAP GRAPHICS --------------- In addition to the extended GW-BASIC-style drawing commands: LOADBMP slot,file$ BITBLT slot,x,y[,keyColor] BITBLT slot,(x,y)[,keyColor] SAVEBMP file$ [,(x1,y1)-(x2,y2)] LOADBMP reads an uncompressed 24-bit or 32-bit Windows BMP into a bitmap slot from 0 through 65535. BITBLT draws the loaded bitmap at the requested physical framebuffer position and clips it to the screen. The destination can be written as flat x,y parameters or as a parenthesized (x,y) point. With keyColor, source pixels matching the low 24 bits of that 0xRRGGBB value are transparent. SAVEBMP writes an uncompressed 24-bit BMP. With no rectangle it saves the active graphics VIEW, or the full graphics screen when no VIEW is active. An explicit (x1,y1)-(x2,y2) rectangle saves exactly that framebuffer region. Examples: LOADBMP 0,"PICS\FOREST.BMP" BITBLT 0,(0,0) BITBLT 0,(100,80),&HFF00FF SAVEBMP "SCREEN.BMP" SAVEBMP "PART.BMP",(100,80)-(399,279) Bitmap pixels are allocated from BASIC data memory and count against FRE. Replacing a loaded slot reclaims its previous pixel block. CLEAR, NEW, RUN or LOAD reclaim all loaded bitmap slots. Bitmap-slot introspection is available without drawing the image: BMPLOADED(slot) -1 if loaded, otherwise 0 BMPWIDTH(slot) pixel width, or 0 if not loaded BMPHEIGHT(slot) pixel height, or 0 if not loaded There is deliberately no BMPKEYCOLOR(): LOADBMP does not store one. BITBLT's optional transparent key belongs to that individual draw operation. LOADBMP/BITBLT is intended for external image assets, SAVEBMP writes framebuffer regions to disk, and GET/PUT captures and restores framebuffer regions in BASIC arrays. SOFTWARE SPRITES ---------------- Sprites use two kinds of slots: image slots 0..65535 loaded pixel data + opacity mask instance slots 0..65535 image reference, position and visibility This separation means one loaded image can be drawn as any number of independent instances without loading or storing the pixel data repeatedly. Load a sprite image: LOADSPRITE image,file$[,transparentColor] Examples: LOADSPRITE 0,"SPRITES\ALIEN.BMP",&HFF00FF LOADSPRITE 1,"SPRITES\SHIP.BMP",&HFF00FF The BMP may be larger than the current screen; drawing is clipped. The practical limit is BASIC memory. LOADSPRITE accepts the same uncompressed 24-bit and 32-bit BMP forms as LOADBMP, with the same 8192-pixel per-side safety limit. If transparentColor is omitted, every source pixel is opaque. Create one or more instances from the same image: SPRITE 0,0,(100,80) SPRITE 1,0,(200,80) SPRITE 2,0,(300,80) The flat coordinate form is accepted too: SPRITE 3,0,400,80 All four instances share image slot 0. SPRITE creates/reassigns the instance and makes it visible. Move or control instances: MOVESPRITE 1,(210,90) MOVESPRITE 1,210,90 HIDESPRITE 2 SHOWSPRITE 2 DELSPRITE 3 MOVESPRITE restores the old background and redraws the affected sprite layer, so moving instances do not leave trails. DELSPRITE removes only the instance; the shared image remains loaded and may still be used by other instances. Remove every active instance at once: SPRITEOFF SPRITEOFF deletes all sprite instances but deliberately keeps the loaded sprite images and their opacity masks. New instances can therefore be created again with SPRITE without reloading the BMP files. Coordinates are physical framebuffer pixels and are not transformed by WINDOW. Negative/off-screen positions are valid; visible portions are clipped. Instance position functions: X=SPRITEX(1) Y=SPRITEY(1) Loaded sprite-image slots can also be inspected: SPRITELOADED(image) -1 if loaded, otherwise 0 SPRITEWIDTH(image) pixel width, or 0 if not loaded SPRITEHEIGHT(image) pixel height, or 0 if not loaded SPRITEKEYCOLOR(image) stored transparency key, or -1 if none/unloaded Pixel-perfect collision: IF SPRITECOLLIDE(0,1) THEN PRINT "HIT" SPRITECOLLIDE returns -1 only when both instances exist, are visible, their rectangles overlap, and at least one pair of opaque source pixels occupies the same position. Hidden instances never collide. A fast rectangle test is done first; only the overlap area is examined pixel-by-pixel. When a transparency color is supplied to LOADSPRITE, Thoreau builds a compact 1-bit opacity mask once while loading the image. Every instance sharing that image also shares its mask. For a 32x32 image the collision mask is only 128 bytes. Text/sprite layering is selectable: SPRITETEXT UNDER SPRITETEXT OVER UNDER is the default and keeps the original behavior: sprite pixels appear over normal text. OVER redraws text foreground pixels after sprite compositing, so HUD text remains visible above moving sprites. Text-cell background pixels are not made into an opaque top layer; if a solid HUD panel is wanted, draw its background explicitly with the normal graphics commands. Sprite images use the BASIC DATA arena and count against FRE(0). Re-loading an image slot returns its old pixel and mask storage to the reusable allocator. CLEAR, NEW, RUN and LOAD discard all sprite images and instances together. LANGUAGE REFERENCE ================== PROGRAM EDITING / EXECUTION --------------------------- AUTO Syntax: AUTO [start][,increment] Does: automatic line numbers; existing lines are marked with * and an immediate Enter preserves the existing line Example: AUTO 1000,10 CHAIN Syntax: CHAIN [MERGE] file$[,[line][,[ALL][,DELETE range]]] Does: load/overlay another program; COMMON controls transferred variables Example: CHAIN MERGE "PART2.BAS",2000 COMMON Syntax: COMMON var[,var...] Does: variables/arrays passed by CHAIN without ALL Example: COMMON SCORE%,PLAYER$ CONT Syntax: CONT Does: continue after STOP or an untrapped break Example: CONT DELETE Syntax: DELETE range Does: remove stored program lines Example: DELETE 1000-1990 EDIT Syntax: EDIT line | EDIT ERL Does: edit a stored line or the last error line Example: EDIT ERL FIND Syntax: FIND string$[,range][,WORD] | FIND NEXT | FIND PREV Does: case-insensitive source search; WORD requires complete BASIC-name boundaries; NEXT/PREV repeat the last search and wrap at either end Example: FIND "PLAYERX",1000-5000,WORD Example: FIND NEXT REPLACE Syntax: REPLACE old$,new$[,range][,WORD] Does: direct-mode source replacement; WORD safely renames BASIC identifiers while ignoring strings, comments and DATA Example: REPLACE "PLAYERX","SHIPX",WORD XREF Syntax: XREF name | XREF array() | XREF line Does: syntax-aware cross-reference for names, arrays or literal line targets Example: XREF SCORE AUDIT Syntax: AUDIT Does: static checks for undefined literal targets, loop-structure mismatches and FN calls lacking DEF FN definitions Example: AUDIT END Syntax: END Does: end program and close files Example: END HELP Syntax: HELP [name] Does: categorized built-in language reference; uses the full physical text screen and wraps at word boundaries, ignoring TXTWINDOW/VIEW PRINT while HELP is displayed Example: HELP LOADBMP LIST Syntax: LIST [range|ERL] [NOWAIT] Does: ERL lists the last error line; ranges: n, n-m, -m, n-; paging is standard, NOWAIT disables it; ESC aborts Example: LIST 1000-2000 NOWAIT LOAD Syntax: LOAD file$ Does: load ASCII BASIC program; omitted extension defaults to .BAS; closing quote may be omitted Example: LOAD "PIXELPROSE CREATEEXE Syntax: CREATEEXE file$ Does: create standalone Windows EXE from the current program; .EXE is added if omitted Platform: Windows only Example: CREATEEXE "PixelProse CREATEEFI Syntax: CREATEEFI file$ Does: create standalone UEFI application from the current program; .EFI is added if omitted Platform: UEFI only Example: CREATEEFI "PixelProse MERGE Syntax: MERGE file$ Does: merge ASCII program lines Example: MERGE "EXTRA.BAS" NEW Syntax: NEW Does: clear program and variables Example: NEW RENUM Syntax: RENUM [new][,old][,increment] Example: RENUM 1000,10,10 RUN Syntax: RUN [line|file$] Does: clear variables and run the stored program; a line number starts at that exact line; file$ is loaded first and defaults to .BAS when no extension is supplied; the closing filename quote may be omitted Example: RUN 1000 Example: RUN "GAME SAVE Syntax: SAVE file$[,A] Does: save ASCII BASIC program; omitted extension defaults to .BAS Example: SAVE "GAME",A STOP Syntax: STOP Does: print "Break in line", pause the program and preserve a continuation; CONT may resume after the STOP Example: STOP REM Syntax: REM comment or apostrophe comment Example: REM this is a comment FLOW / ERRORS / DIAGNOSTICS --------------------------- ERROR Syntax: ERROR n Does: raise an error Example: ERROR 5 FOR Syntax: FOR v=start TO limit [STEP step] ... NEXT | FOR END Does: FOR END exits the innermost active FOR and continues after its NEXT Example: FOR I=1 TO 10 STEP 2 PARFOR Syntax: PARFOR v=start TO limit [STEP positive-integer] ... NEXT [v] Does: execute independent iterations in parallel using the native JIT. Unlike FOR, execution order is not defined. The complete reachable loop/GOSUB graph is checked before workers start; unsafe or interpreter-only statements are rejected with a reason and suggested workaround rather than being executed concurrently by accident. Numeric and @ scalar scratch variables are private to each worker. Their worker-local final values are not a communication mechanism between iterations. Numeric/@ arrays are shared. Array reads are allowed; stores are accepted only when the compiler can prove that workers address disjoint elements/slices, normally because one subscript is exactly the PARFOR variable. Absolute PSET and supported LINE forms require an explicit colour and should target disjoint pixels/regions. Shared text cursor/output, WINDOW/VIEW transforms, active event handlers, PROFILE/tracing, debugger breakpoints, nested PARFOR and any path requiring classic interpreter fallback are rejected. JIT must be ON. Start and limit must currently be integers; STEP must be a positive integer. With OPTION PARTHREADS 0, Thoreau autotunes worker count and may run a small PARFOR on one worker when threading would be slower. Windows and UEFI keep worker pools alive across repeated PARFOR calls during a RUN; on UEFI the AP pool is started through MP Services only as needed and is shut down when execution returns to Ready. Example: PARFOR Y=0 TO GRAMAXY FOR X=0 TO GRAMAXX PSET (X,Y),0,0,0 NEXT X NEXT Y PARTHREADS Syntax: PARTHREADS Does: read the configured PARFOR worker limit; 0 means automatic tuning Example: PRINT PARTHREADS PARWORKERS Syntax: PARWORKERS Does: effective number of workers used by the most recent PARFOR Example: PRINT PARWORKERS GOSUB Syntax: GOSUB line Does: call subroutine Example: GOSUB 9000 GOTO Syntax: GOTO line Does: branch Example: GOTO 1000 IF Syntax: IF condition THEN ... [ELSE ...] Does: conditional statement; in nested single-line forms each ELSE binds to the nearest unmatched IF, including across GOSUB/RETURN Example: IF SCORE>100 THEN 5000 ELSE 2000 NEXT Syntax: NEXT [v[,v...]] Does: end one or more nested FOR loops in the listed order Example: NEXT K,J,I ON Syntax: ON expr GOTO/GOSUB ...; ON ERROR/BREAK GOTO line; ON MOUSEMOVE/MOUSECLICK GOSUB line Example: ON CHOICE GOTO 1000,2000,3000 Example: ON MOUSECLICK GOSUB 9000 RESUME Syntax: RESUME [NEXT|0|line] Example: RESUME NEXT RETURN Syntax: RETURN Does: return from GOSUB Example: RETURN TROFF Syntax: TROFF Does: disable line-number tracing Example: TROFF TRON Syntax: TRON [line[-line]] Does: trace all lines or only the selected line/range Example: TRON 1000-2000 TRACE Syntax: TRACE var[,var...] Does: show selected scalar values as program lines execute; TRACE OFF clears watches Example: TRACE SCORE%,ROOM% JIT Syntax: JIT ON | JIT OFF | JIT Does: enable/disable all bytecode and native JIT acceleration; JIT OFF forces the classic interpreter, while bare JIT reports ON/OFF Example: JIT OFF PROFILE Syntax: PROFILE [ALL] | PROFILE ON [MARK] | PROFILE MARK [ON|OFF] | PROFILE JIT | PROFILE SAMPLE | PROFILE EXACT | PROFILE INTERPRETER | PROFILE OFF | PROFILE CLEAR Does: measure executed source lines. ON/JIT/SAMPLE keep compiled execution active and use low-overhead timing samples; EXACT/INTERPRETER use exact interpreter profiling and disable compiled fast paths. Reports include RUNS, JITRUNS, INTRUNS and MODE. Bare PROFILE shows the 20 hottest lines; ALL shows all sampled lines in source order. PROFILE MARK, PROFILE MARK ON and PROFILE ON MARK enable statement execution marking, clear previous statistics/marks and start the normal JIT-aware sampled profiler. After RUN, LIST colours each executed statement according to the engine that actually handled it: GREEN executed by JIT YELLOW executed by the interpreter, but the statement itself has JIT support; surrounding control flow/region shape kept it interpreted in that run RED executed by the interpreter and currently has no JIT implementation for that statement/syntax NORMAL statement was not reached in the marked run PROFILE MARK OFF disables statement marking and restores ordinary LIST colours without discarding the collected timing/count statistics. PROFILE OFF stops profiling while retaining samples and the MARK colours from the last run. PROFILE CLEAR clears both statistics and statement marks. Source edits also invalidate the stored marks. Example: PROFILE ON MARK Example: PROFILE MARK OFF WHILE Syntax: WHILE condition ... WEND | WHILE END Does: WHILE END exits the innermost active WHILE and continues after WEND Example: WHILE A<10 WEND Syntax: WEND Does: end WHILE loop Example: WEND ERL Syntax: ERL Does: line number of last error Example: PRINT ERL ERR Syntax: ERR Does: last error number Example: PRINT ERR VARINFO Syntax: VARINFO [SIMPLE|FULL|0|1] Does: list scalar variables; FULL adds type/value/address; output pauses each screen Example: VARINFO FULL ARRAYINFO Syntax: ARRAYINFO [SIMPLE|FULL|0|1] Does: list arrays; FULL adds type/size/address; output pauses each screen Example: ARRAYINFO FULL VARIABLES / DATA / CONVERSION ----------------------------- CLEAR Syntax: CLEAR Does: clear variables/data Example: CLEAR DATA Syntax: DATA values Does: embedded program data Example: DATA 10,20,"forest" DEFDBL Syntax: DEFDBL letters Does: default double type; an unsuffixed name aliases its matching suffix Example: DEFDBL A-Z DEFI64 Syntax: DEFI64 letters Does: default 64-bit integer type; an unsuffixed name aliases its matching suffix Example: DEFI64 A-Z DEFINT Syntax: DEFINT letters Does: default integer type; an unsuffixed name aliases its matching suffix Example: DEFINT I-N DEFLNG Syntax: DEFLNG letters Does: default long type; an unsuffixed name aliases its matching suffix Example: DEFLNG L DEFSNG Syntax: DEFSNG letters Does: default single type; an unsuffixed name aliases its matching suffix Example: DEFSNG S DEFSTR Syntax: DEFSTR letters Does: default string type; an unsuffixed name aliases its matching suffix Example: DEFSTR A-C DIM Syntax: DIM array(bounds) Does: dimension a new array Example: DIM MAP%(100) REDIM Syntax: REDIM array(bounds) Does: create or replace an array; contents are discarded and its address may change Example: REDIM MAP%(500) ERASE Syntax: ERASE array[,array...] Does: undefine arrays and return their storage for reuse; nonexistent arrays are ignored; other live array addresses do not move Example: ERASE MAP% OPTION Syntax: OPTION BASE 0|1 OPTION PARTHREADS 0..32 Does: BASE selects the default array lower bound. PARTHREADS sets the PARFOR worker limit; 0 enables automatic tuning, while 1..32 caps the requested number of workers. Example: OPTION BASE 1 Example: OPTION PARTHREADS 0 READ Syntax: READ variables Does: consume DATA Example: READ X,Y,NAME$ RESTORE Syntax: RESTORE [line] Does: reset DATA pointer Example: RESTORE 1000 SWAP Syntax: SWAP a,b Example: SWAP A,B CDBL Syntax: CDBL(x) Does: convert to double Example: X#=CDBL(A) CINT Syntax: CINT(x) Does: convert to integer Example: I%=CINT(X) CSNG Syntax: CSNG(x) Does: convert to single Example: S!=CSNG(X) CVD Syntax: CVD(s$) Does: MBF double from 8 bytes Example: X#=CVD(B$) CVI Syntax: CVI(s$) Does: integer from 2 bytes Example: I%=CVI(B$) CVS Syntax: CVS(s$) Does: MBF single from 4 bytes Example: S!=CVS(B$) MKD$ Syntax: MKD$(x) Does: 8-byte MBF double Example: B$=MKD$(X#) MKI$ Syntax: MKI$(n) Does: 2-byte integer Example: B$=MKI$(I%) MKS$ Syntax: MKS$(x) Does: 4-byte MBF single Example: B$=MKS$(S!) VARPTR Syntax: VARPTR(variable) Does: 64-bit address Example: PRINT HEX$(VARPTR(A)) HYPERCOMPLEX VARIABLES Syntax: name@ | name@(subscripts) | name@.R/.I/.J/.K/.E1..E7 Does: store complex, quaternion or octonion values in one native type; supports + - * / and ^ with a real scalar exponent Example: Q@=QUAT(1,2,3,4):PRINT Q@^.5 FUNCTIONS --------- DEF FN Syntax: DEF FNname(args)=expr Does: define a user function whose body is one expression Example: DEF FNSQUARE(X)=X*X IIF Syntax: IIF(condition,ifTrue,ifFalse) Does: evaluate condition, then evaluate and return only the selected branch; the unselected expression is not evaluated Example: DEF FNSAFE(X)=IIF(X=0,0,1/X) ABS Syntax: ABS(x) Does: absolute value; for @ values returns Euclidean magnitude Example: PRINT ABS(CPLX(3,4)) CPLX Syntax: CPLX(real,i) Does: construct a complex @ value Example: Z@=CPLX(3,4) QUAT Syntax: QUAT(real,i,j,k) Does: construct a quaternion @ value Example: Q@=QUAT(1,2,3,4) OCT Syntax: OCT(real,e1,e2,e3,e4,e5,e6,e7) Does: construct an octonion @ value Example: O@=OCT(1,2,3,4,5,6,7,8) CONJ Syntax: CONJ(x) Does: hypercomplex conjugate Example: PRINT CONJ(CPLX(3,4)) INV Syntax: INV(x) Does: multiplicative inverse; A@/B@ is defined as A@*INV(B@) Example: PRINT INV(QUAT(1,2,3,4)) NORM Syntax: NORM(x) Does: Euclidean magnitude Example: PRINT NORM(CPLX(3,4)) NORM2 Syntax: NORM2(x) Does: squared Euclidean norm Example: PRINT NORM2(CPLX(3,4)) COMP Syntax: COMP(x,n) Does: return hypercomplex component 0..7; component 0 is real Example: PRINT COMP(QUAT(1,2,3,4),3) ASC Syntax: ASC(s$) Does: character code Example: PRINT ASC("A") ATN Syntax: ATN(x) Does: arctangent Example: PRINT ATN(1) CHR$ Syntax: CHR$(n) Does: one-character string Example: PRINT CHR$(65) COS Syntax: COS(x) Does: cosine; accepts scalar or @ values Example: PRINT COS(CPLX(1,2)) COSH Syntax: COSH(x) Does: hyperbolic cosine; accepts scalar or @ values Example: PRINT COSH(QUAT(1,2,3,4)) EXP Syntax: EXP(x) Does: exponential; accepts scalar or @ values Example: PRINT EXP(CPLX(0,1)) FIX Syntax: FIX(x) Does: truncate toward zero Example: PRINT FIX(-3.7) HEX$ Syntax: HEX$(n) Does: hexadecimal string Example: PRINT HEX$(255) INSTR Syntax: INSTR([start,]string$,search$) Example: PRINT INSTR("FOREST","REST") INT Syntax: INT(x) Does: floor Example: PRINT INT(-3.7) LCASE$ Syntax: LCASE$(s$) Does: convert ASCII A-Z to lowercase Example: PRINT LCASE$("GORSE") UCASE$ Syntax: UCASE$(s$) Does: convert ASCII a-z to uppercase Example: PRINT UCASE$("gorse") LEFT$ Syntax: LEFT$(s$,n) Example: PRINT LEFT$("THOREAU",3) LEN Syntax: LEN(s$) Example: PRINT LEN("BASIC") LOG Syntax: LOG(x) Does: natural logarithm; @ values use the documented principal branch Example: PRINT LOG(QUAT(-1,0,0,0)) MID$ Syntax: MID$(s$,start[,len]) or MID$(s$,start[,len])=value$ Example: MID$(A$,2,3)="XYZ" OCT$ Syntax: OCT$(n) Does: octal string Example: PRINT OCT$(64) RIGHT$ Syntax: RIGHT$(s$,n) Example: PRINT RIGHT$("THOREAU",4) RND Syntax: RND[(x)] Does: random number Example: PRINT RND(1) SGN Syntax: SGN(x) Does: sign Example: PRINT SGN(-9) SIN Syntax: SIN(x) Does: sine; accepts scalar or @ values Example: PRINT SIN(CPLX(1,2)) SINH Syntax: SINH(x) Does: hyperbolic sine; accepts scalar or @ values Example: PRINT SINH(QUAT(1,2,3,4)) SPACE$ Syntax: SPACE$(n) Example: PRINT "A"+SPACE$(5)+"B" SQR Syntax: SQR(x) Does: square root; @ values use the documented principal root Example: PRINT SQR(CPLX(-1,0)) SQRT Syntax: SQRT(x) Does: alias for SQR; @ values use the documented principal root Example: PRINT SQRT(OCT(-1,0,0,0,0,0,0,0)) STR$ Syntax: STR$(x) Does: number to string; @ values use canonical component notation Example: A$=STR$(42) STRING$ Syntax: STRING$(n,char) Example: PRINT STRING$(20,"*") TAN Syntax: TAN(x) Does: tangent; accepts scalar or @ values Example: PRINT TAN(CPLX(1,2)) TANH Syntax: TANH(x) Does: hyperbolic tangent; accepts scalar or @ values Example: PRINT TANH(QUAT(1,2,3,4)) VAL Syntax: VAL(s$) Does: string to number Example: PRINT VAL("123.5") VIDEOMODES Syntax: VIDEOMODES() Does: number of physical/display video modes available for enumeration Example: FOR I=0 TO VIDEOMODES()-1 INPUT / OUTPUT -------------- CLS Syntax: CLS [@n] Does: clear screen/text window; Ctrl+L at the interactive prompt clears the screen and current edit line Example: CLS COLOR Syntax: COLOR fg[,bg] | COLOR r,g,b | COLOR r,g,b,rb,gb,bb Does: set foreground/background; 0-15 = palette, >15 = packed 0xRRGGBB Example: COLOR 255,136,0,16,16,16 CSRLIN Syntax: CSRLIN Does: current text row Example: PRINT CSRLIN INKEY$ Syntax: INKEY$ Does: nonblocking key string; supported extended keys return the classic two-byte form CHR$(0)+CHR$(DOS scan) Example: K$=INKEY$ Example: IF K$=CHR$(0)+CHR$(72) THEN PRINT "UP" KEYDOWN Syntax: KEYDOWN(key$) Does: -1 while the named key is currently held; does not consume INKEY$ Example: IF KEYDOWN("LEFT") AND KEYDOWN("SPACE") THEN GOSUB 9000 KEYSTATEAVAILABLE Syntax: KEYSTATEAVAILABLE or KEYSTATEAVAILABLE() Does: -1 when true held-key state is available; UEFI requires raw USB HID Example: IF NOT KEYSTATEAVAILABLE THEN PRINT "No held-key state" KEYREPEAT Syntax: KEYREPEAT delayMilliseconds,rateHz | KEYREPEAT DEFAULT Does: custom typematic timing on Windows and raw USB HID UEFI; firmware UEFI fallback keeps firmware repeat timing Example: KEYREPEAT 0,30 MOUSE Syntax: MOUSE ON | MOUSE OFF Does: show or hide the pointer; mouse state remains readable either way Example: MOUSE ON MOUSEPOS Syntax: MOUSEPOS x,y Does: set logical mouse position in physical framebuffer pixels Example: MOUSEPOS 320,240 MOUSEX / MOUSEY Syntax: MOUSEX() | MOUSEY() Does: current logical pointer coordinates in framebuffer pixels Example: PRINT MOUSEX(),MOUSEY() MOUSEB Syntax: MOUSEB() Does: button bitmask: 1 left, 2 right, 4 middle where available Example: IF MOUSEB() AND 1 THEN PRINT "LEFT" MOUSEWHEEL Syntax: MOUSEWHEEL() Does: cumulative signed wheel movement Example: W=MOUSEWHEEL() MOUSEPRESENT Syntax: MOUSEPRESENT or MOUSEPRESENT() Does: -1 when a pointing device is available, else 0 Example: IF MOUSEPRESENT THEN MOUSE ON INPUT Syntax: INPUT [;][prompt;] variables or INPUT #n,... Does: read values; a leading semicolon keeps the cursor on the current line after Enter instead of advancing to the next text row Example: INPUT ;"A=",A INPUT$ Syntax: INPUT$(count[,[#]n]) Does: read characters Example: A$=INPUT$(1) LOCATE Syntax: LOCATE [@n,]row,col Example: LOCATE 10,20 POS Syntax: POS(x) Does: current text column Example: PRINT POS(0) PRINT Syntax: PRINT expressions; PRINT USING; PRINT #; PRINT @; PRINT WRAP [width,]string$; PRINT JUSTIFY [width,]string$ Example: PRINT WRAP 60,TEXT$ SPC Syntax: SPC(n) Does: PRINT spacing Example: PRINT "A";SPC(5);"B" TAB Syntax: TAB(n) Does: PRINT tab position Example: PRINT TAB(20);"column 20" TXTWINDOW Syntax: TXTWINDOW col1,row1,col2,row2 sets the normal text region; bare TXTWINDOW restores full screen; TXTWINDOW @n,col1,row1,col2,row2 defines a named region Does: define a 1-based text-cell rectangle (columns and rows, not graphics x/y coordinates) Example: TXTWINDOW 1,20,80,30 TXTMAXX Syntax: TXTMAXX Does: text columns Example: PRINT TXTMAXX TXTMAXY Syntax: TXTMAXY Does: text rows Example: PRINT TXTMAXY WRITE Syntax: WRITE values or WRITE #n,values Example: WRITE "room",ROOM% NETWORK ------- TCP Syntax: TCP OPEN slot,host$,port | TCP SEND slot,data$ | TCP CLOSE slot | TCP TIMEOUT milliseconds Does: TCP/IPv4 client networking with slots 0..7; timeout range 1..600000 ms Example: TCP OPEN 0,"example.com",80 TCPRECV$ Syntax: TCPRECV$(slot[,maxBytes]) Does: receive up to maxBytes from a TCP slot; default 4096, maximum 1048576 Example: A$=TCPRECV$(0) TCPCONNECTED Syntax: TCPCONNECTED(slot) Does: -1 while the TCP slot is open and connected Example: IF TCPCONNECTED(0) THEN PRINT "CONNECTED" TCPEOF Syntax: TCPEOF(slot) Does: -1 after the remote peer closes the connection Example: IF TCPEOF(0) THEN TCP CLOSE 0 DNS$ Syntax: DNS$(host$) Does: resolve a host name to an IPv4 dotted-decimal string Example: PRINT DNS$("example.com") NETPRESENT Syntax: NETPRESENT() Does: -1 when a usable IPv4 network stack is available Example: IF NOT NETPRESENT() THEN PRINT "NO NETWORK" NETINFO Syntax: NETINFO Does: display network backend, protocol/fallback availability, IPv4 configuration and the most recent network error; UEFI includes SNP/PXE/Managed Network/DHCP4/IP4/UDP4/DNS4/TCP4/HTTP/TLS status Example: NETINFO HTTPGET$ Syntax: HTTPGET$(url$[,headers$]) Does: HTTP/HTTPS GET; optional headers are CR/LF-separated Name: value lines; response body is limited to 1 MiB Example: J$=HTTPGET$("https://example.com/") HTTPSTATUS Syntax: HTTPSTATUS() Does: numeric status from the most recent HTTPGET$ Example: PRINT HTTPSTATUS() NETERROR$ Syntax: NETERROR$() Does: text for the most recent network error Example: IF J$="" THEN PRINT NETERROR$() FILES / DIRECTORIES ------------------- APPEND Syntax: APPEND Does: OPEN mode Example: OPEN "LOG.TXT" FOR APPEND AS #1 AS Syntax: AS Does: OPEN/FIELD syntax word Example: OPEN "SAVE.DAT" FOR OUTPUT AS #1 BLOAD Syntax: BLOAD file$[,address] Does: load GW memory image Example: BLOAD "IMAGE.BIN",&H10000 BSAVE Syntax: BSAVE file$,address,length Does: save GW memory image Example: BSAVE "IMAGE.BIN",&H10000,4096 CHDIR Syntax: CHDIR path$ Does: change directory Example: CHDIR "GAMES" CLOSE Syntax: CLOSE [#n,...] Does: close files Example: CLOSE #1 EOF Syntax: EOF(n) Does: end-of-file state Example: WHILE NOT EOF(1) FIELD Syntax: FIELD #n,width AS s$,... Does: map random-file record fields Example: FIELD #1,20 AS NAME$,4 AS SCORE$ DIR Syntax: DIR [pattern$][,S][,W][,P] Does: alias for FILES; names and paths print uppercase; S recurses, W wide listing, P pauses; ESC aborts listing/traversal Example: DIR "*.BAS",S,W,P FILES Syntax: FILES [pattern$][,S][,W][,P] Does: names and paths print uppercase; directories come first with [DIR] and case-insensitive sorting; wildcards are supported; S recurses, W uses wide output, P pauses; ESC aborts Example: FILES "*.BMP",W GET Syntax: GET (x1,y1)-(x2,y2),array or GET #n[,record] Does: graphics GET stores a full 24-bit framebuffer rectangle in a numeric array Example: GET (0,0)-(63,63),SPR& File example: GET #1,5 KILL Syntax: KILL filespec$ Does: delete one or more files; * and ? wildcards are supported; wildcard deletion is non-recursive and never removes directories Example: KILL "*.TMP" LOC Syntax: LOC(n) Does: file position/record Example: PRINT LOC(1) LOF Syntax: LOF(n) Does: file length Example: PRINT LOF(1) LSET Syntax: LSET field$=value$ Does: left-align random field Example: LSET NAME$="THOREAU" MKDIR Syntax: MKDIR path$ Does: create directory Example: MKDIR "SAVES" NAME Syntax: NAME old$ AS new$ Does: rename file/directory Example: NAME "OLD.SAV" AS "NEW.SAV" OPEN Syntax: OPEN file$ FOR mode AS #n or classic OPEN mode,#n,file$ Example: OPEN "SAVE.DAT" FOR INPUT AS #1 OUTPUT Syntax: OUTPUT Does: OPEN mode Example: OPEN "OUT.TXT" FOR OUTPUT AS #1 PUT Syntax: PUT (x,y),array[,PSET|PRESET|XOR|AND|OR] or PUT #n[,record] Does: graphics PUT restores 24-bit GET data; default graphics mode is XOR Example: PUT (200,100),SPR&,PSET File example: PUT #1,5 RMDIR Syntax: RMDIR path$ Does: remove empty directory Example: RMDIR "EMPTYDIR" RSET Syntax: RSET field$=value$ Does: right-align random field Example: RSET SCORE$=MKI$(1000) GRAPHICS -------- BITBLT Syntax: BITBLT slot,x,y[,keyColor] or BITBLT slot,(x,y)[,keyColor] Does: draw bitmap slot 0..65535 at a physical framebuffer position; optional keyColor is transparent Example: BITBLT 0,(100,80),&HFF00FF BMPLOADED / BMPWIDTH / BMPHEIGHT Syntax: BMPLOADED(slot) | BMPWIDTH(slot) | BMPHEIGHT(slot) Does: query whether a LOADBMP slot is present and its dimensions Example: IF BMPLOADED(0) THEN PRINT BMPWIDTH(0),BMPHEIGHT(0) CIRCLE Syntax: CIRCLE [STEP](x,y),radius[,color[,start[,end[,aspect]]]] Does: draw a circle; color is palette 0-15 or packed 0xRRGGBB; start/end/aspect are currently ignored Example: CIRCLE (320,240),100,&HFF8800 DRAW Syntax: DRAW string$ Does: GW Graphics Macro Language (U,D,L,R,E,F,G,H,M,B,N,A,TA,C,S,P); Ppaint,border flood-fills at the current point Example: COL&&=&HFF8800 : DRAW "C=COL&&;R40D40L40U40P=COL&&;,0" GRAMAXX Syntax: GRAMAXX Does: graphics width Example: PRINT GRAMAXX GRAMAXY Syntax: GRAMAXY Does: graphics height Example: PRINT GRAMAXY GRAPITCH Syntax: GRAPITCH Does: framebuffer pixels per row Example: PRINT GRAPITCH LINE Syntax: LINE [[STEP](x1,y1)]-[STEP](x2,y2)[,color|r,g,b][,B|BF] or LINE INPUT Does: draw line/box/filled box; graphics color may be palette, packed 0xRRGGBB or RGB triple Example: LINE (10,10)-(200,100),255,136,0,BF LOADBMP Syntax: LOADBMP slot,file$ Does: load an uncompressed 24/32-bit BMP into slot 0..65535 Example: LOADBMP 0,"FOREST.BMP" LOADSPRITE Syntax: LOADSPRITE image,file$[,transparentColor] Does: load sprite image 0..65535 and build its shared opacity mask Example: LOADSPRITE 0,"SPRITES\ALIEN.BMP",&HFF00FF SPRITE Syntax: SPRITE instance,image,(x,y) or SPRITE instance,image,x,y Does: create/reassign/show instance 0..65535 using a loaded image Example: SPRITE 12,0,(100,80) MOVESPRITE Syntax: MOVESPRITE instance,(x,y) or MOVESPRITE instance,x,y Does: move an instance with background restoration; coordinates are physical Example: MOVESPRITE 12,(110,84) SHOWSPRITE Syntax: SHOWSPRITE instance Does: make an existing hidden instance visible Example: SHOWSPRITE 12 HIDESPRITE Syntax: HIDESPRITE instance Does: hide an instance; hidden sprites do not collide Example: HIDESPRITE 12 DELSPRITE Syntax: DELSPRITE instance Does: delete one instance without unloading its shared image Example: DELSPRITE 12 SPRITEOFF Syntax: SPRITEOFF Does: delete all sprite instances at once; loaded sprite images remain available and can be reused by later SPRITE commands Example: SPRITEOFF SPRITETEXT Syntax: SPRITETEXT UNDER | SPRITETEXT OVER Does: UNDER composites sprites over text; OVER redraws text foreground pixels above sprites, useful for HUDs and labels Example: SPRITETEXT OVER SPRITEX Syntax: SPRITEX(instance) Does: physical x coordinate of an existing instance Example: PRINT SPRITEX(12) SPRITEY Syntax: SPRITEY(instance) Does: physical y coordinate of an existing instance Example: PRINT SPRITEY(12) SPRITECOLLIDE Syntax: SPRITECOLLIDE(instance1,instance2) Does: -1 for at least one overlapping pair of opaque source pixels, else 0 Example: IF SPRITECOLLIDE(10,100) THEN PRINT "HIT" SPRITELOADED / SPRITEWIDTH / SPRITEHEIGHT / SPRITEKEYCOLOR Syntax: function(image) Does: query a loaded sprite-image slot, its dimensions and stored key color (-1 if none) Example: IF SPRITELOADED(0) THEN PRINT SPRITEWIDTH(0),SPRITEHEIGHT(0) SAVEBMP Syntax: SAVEBMP file$ [,(x1,y1)-(x2,y2)] Does: save the active graphics VIEW, full screen, or an explicit framebuffer rectangle as an uncompressed 24-bit BMP Example: SAVEBMP "SCREEN.BMP" Example: SAVEBMP "PART.BMP",(100,80)-(399,279) PAINT Syntax: PAINT [STEP](x,y)[,paint|r,g,b[,border]] Does: flood fill; paint accepts palette/packed RGB or an RGB triple; border is palette/packed RGB Example: PAINT (100,100),32,64,128,&HFFFFFF POLYFILL Syntax: POLYFILL (x1,y1),(x2,y2),(x3,y3)[,...][,color|r,g,b] Does: fill a concave or convex polygon with the even-odd rule; STEP vertices are relative to the preceding vertex Example: POLYFILL (20,20),(180,40),(130,160),(40,120),255,136,0 POINT Syntax: POINT(x,y) Does: exact CGA colors return palette 0-15; otherwise returns packed 24-bit 0xRRGGBB; -1 off screen Example: PRINT HEX$(POINT(100,100)) PRESET Syntax: PRESET [STEP](x,y)[,color|r,g,b] Does: set pixel; explicit color accepts palette, packed 0xRRGGBB or RGB triple; default is background Example: PRESET (10,10),255,0,0 PSET Syntax: PSET [STEP](x,y)[,color|r,g,b] Does: set pixel; color accepts palette, packed 0xRRGGBB or RGB triple Example: PSET (10,10),255,136,0 SCREEN Syntax: SCREEN width,height | SCREEN MODE n | SCREEN MODES | SCREEN(row,col) Does: Windows selects a logical framebuffer size; UEFI selects exact GOP dimensions. SCREEN MODES lists physical/display modes. The function form returns the character code stored in a text cell. Example: SCREEN 960,540 Example: PRINT CHR$(SCREEN(10,20)) VIDEOMODE Syntax: VIDEOMODE n,widthVar,heightVar Does: query the width and height of physical/display mode n Example: VIDEOMODE I,W,H SCRNADR Syntax: SCRNADR Does: framebuffer address Example: PRINT HEX$(SCRNADR) VIEW Syntax: VIEW [SCREEN] (x1,y1)-(x2,y2)[,fill[,border]]; VIEW PRINT top TO bottom Does: graphics VIEW clips drawing; fill/border accept palette or packed 0xRRGGBB. SCREEN is GW coordinate semantics, not a display page. Example: VIEW SCREEN (0,0)-(639,479),&H101820,&HFFFFFF WINDOW Syntax: WINDOW [SCREEN] (x1,y1)-(x2,y2) Does: logical coordinates. SCREEN makes Y increase downward; it is not a display page. Example: WINDOW SCREEN (0,0)-(100,100) MEMORY / SYSTEM --------------- SYSTEM Syntax: SYSTEM Does: leave Thoreau BASIC; Windows closes the application; UEFI returns to the firmware/caller Example: SYSTEM KEYB Syntax: KEYB [xx] Does: UEFI only: show or switch the current keyboard layout; THOREAU.CFG beside the EFI accepts KEYB xx at startup; default is US Layouts: BE BR DK GR SU FR UK IT YU CF LA NL NO PL PO SV SG SF SP SL CZ HU US Example: KEYB GR THOREAU Syntax: THOREAU Does: enter DebuggerMode; STATE, STACK, FLOW, BREAKS, TIMERS and INTERNALS inspect the live interpreter; X restores the prior display/settings; THOREAU LANDMARKS, MEMMAP or INFO provides direct views Example: THOREAU THOREAUADR Syntax: THOREAUADR(name$) Does: 64-bit address of a named machine landmark Example: PRINT HEX$(THOREAUADR("FRAMEBUFFER")) DATE$ Syntax: DATE$ Does: current date Example: PRINT DATE$ FREEBOT Syntax: FREEBOT Does: bottom of free data memory Example: PRINT FREEBOT FREETOP Syntax: FREETOP Does: top of free data memory Example: PRINT FREETOP FRE Syntax: FRE(x) Does: free BASIC data bytes, including reusable blocks returned by ERASE/bitmap replacement Example: PRINT FRE(0) HIMEM Syntax: HIMEM Does: high memory address Example: PRINT HIMEM LOMEM Syntax: LOMEM Does: low memory address Example: PRINT LOMEM PEEK Syntax: PEEK(address) Does: read byte at 64-bit address Example: PRINT PEEK(HIMEM-1) POKE Syntax: POKE address,byte Example: POKE LOMEM,255 PEEK16 Syntax: PEEK16(address) Does: read unsigned 16-bit little-endian value Example: PRINT PEEK16(LOMEM) PEEK32 Syntax: PEEK32(address) Does: read unsigned 32-bit little-endian value Example: PRINT PEEK32(LOMEM) PEEK64 Syntax: PEEK64(address) Does: read raw 64-bit little-endian value as && Example: PRINT PEEK64(LOMEM) POKE16 Syntax: POKE16 address,value Does: write 16-bit little-endian value Example: POKE16 LOMEM,4660 POKE32 Syntax: POKE32 address,value Does: write 32-bit little-endian value Example: POKE32 LOMEM,&H12345678 POKE64 Syntax: POKE64 address,value Does: write all 64 bits of an && value Example: POKE64 LOMEM,123456789&& TIME$ Syntax: TIME$ Does: current time Example: PRINT TIME$ TIMER Syntax: TIMER Does: seconds since boot; TIMER(n) returns interval ms; TIMER(n)=ms sets; TIMER(n) ON/OFF controls timer n Example: TIMER(0)=1000 : ON TIMER(0) GOSUB 9000 : TIMER(0) ON WAITREL Syntax: WAITREL milliseconds Does: relative frame pacing; waits only for the remaining time since the previous WAITREL returned; late frames return immediately and re-anchor instead of catching up Example: WAITREL 16 COMMANDLINEARG$ Syntax: COMMANDLINEARG$(n) Does: 1-based command-line argument after the autostart program; empty string if absent Platform: Windows only Example: PRINT COMMANDLINEARG$(1) STARTUP.BAS Syntax: STARTUP.BAS Does: UEFI startup program automatically loaded and run when no explicit autostart program is supplied Platform: UEFI interpreter startup feature Example: Create STARTUP.BAS containing: LOAD "MENU" : RUN OPERATORS / SYNTAX WORDS ------------------------ AND Syntax: AND Does: bitwise/logical conjunction Example: IF A AND B THEN PRINT "both" BASE Syntax: BASE Does: used by OPTION BASE Example: OPTION BASE 1 BREAK Syntax: BREAK [LIST] lists breakpoints; BREAK line[,line...] sets; BREAK DELETE line removes; BREAK CLEAR clears. ON BREAK GOTO remains supported Example: BREAK 1000,2000 ELSE Syntax: ELSE Does: alternate IF branch Example: IF A=1 THEN PRINT "one" ELSE PRINT "other" EQV Syntax: EQV Does: logical equivalence Example: PRINT A EQV B IMP Syntax: IMP Does: logical implication Example: PRINT A IMP B LET Syntax: LET variable=expression Example: LET A=42 MOD Syntax: MOD Does: integer remainder Example: PRINT 17 MOD 5 NOT Syntax: NOT Does: bitwise/logical negation Example: PRINT NOT 0 OR Syntax: OR Does: bitwise/logical disjunction Example: IF A OR B THEN PRINT "yes" RANDOMIZE Syntax: RANDOMIZE [seed] Example: RANDOMIZE TIMER STEP Syntax: STEP Does: FOR increment or relative graphics point Example: FOR X=0 TO 100 STEP 5 ON TIMER Syntax: ON TIMER(n) GOSUB line Does: bind timer n (0..7) to a GOSUB handler Example: ON TIMER(0) GOSUB 9000 THEN Syntax: THEN Does: IF consequence Example: IF READY THEN GOTO 1000 TO Syntax: TO Does: FOR/VIEW PRINT range word Example: FOR I=1 TO 10 USING Syntax: USING Does: PRINT formatting word Example: PRINT USING "###.##";X XOR Syntax: XOR Does: bitwise/logical exclusive OR Example: PRINT A XOR B THOREAU MACHINE EXPLORER ======================== Enter it from BASIC with: THOREAU F12 enters the same protected DebuggerMode from the BASIC prompt, during INPUT, or while a program is running. The debugger starts on a cleared screen with normal key repeat and sprites temporarily hidden. X returns to the prompt or resumes the interrupted program after restoring the framebuffer, text grid, cursor, colors, text/graphics views, sprite presentation and KEYREPEAT settings. Numbers in the monitor are hexadecimal by default. Prefix a decimal value with D:, for example D:4096. Core monitor commands: STATE Summarize execution state, current/continuation locations, last pause or error, program/variable/file/stack counts, breakpoints, timers and tracing. STACK Show the live GOSUB and programmable-timer call stack, newest frame first. FLOW Show FOR, WHILE, ERROR/BREAK handler and single-line IF control frames. BREAKS Show the last pause, CONT target and active source-line breakpoints. TIMERS Show every configured programmable timer, handler, deadline and state. INTERNALS Show addresses and capacities of the interpreter's principal structures. L Show named machine/interpreter landmarks. Example: L M [address [length]] Hex/ASCII memory dump. M alone continues from the previous dump. Example: M LOMEM 100 M! address [length] UEFI only: force a read of a normally refused/protected region. Windows deliberately does not provide forced protected reads. Example: M! 100000 100 F start end byte Fill memory. Example: F 100000 1000FF 00 C start1 end1 start2 Compare two memory blocks. Example: C 100000 1000FF 200000 > address hex... Enter hexadecimal bytes. Example: > 100000 48 65 6C 6C 6F A address text... Enter ASCII bytes. Example: A 100000 HELLO H start end hex... Hunt for a hexadecimal byte sequence. Example: H 100000 110000 DE AD BE EF HA start end text... Hunt for ASCII text. Example: HA 100000 110000 THOREAU T start end dest Transfer/copy memory. Example: T 100000 1000FF 200000 SAVE file start end Save raw memory to a file. Example: SAVE dump.bin 100000 100FFF LOAD file address Load a raw file into memory. Example: LOAD dump.bin 200000 R address Describe the containing memory region. Example: R LOMEM W address Show nearest landmark and containing region. Example: W FRAMEBUFFER V address View BYTE/WORD/DWORD/QWORD and typed interpretations. Example: V LOMEM MAP Show the platform memory map. Example: MAP I Show compact machine information. Example: I Read-only storage / boot inspection: DISKS Enumerate disks / whole-media devices. Example: DISKS DISK n Show disk/media details. Example: DISK 0 SECTOR n lba [count] Dump raw sectors as hex/ASCII. Example: SECTOR 0 0 1 PARTITIONS n Show GPT/MBR partition information. Example: PARTITIONS 0 PARTITION n p Show one partition in detail. Example: PARTITION 0 1 VOLUMES Enumerate mounted/accessible filesystems. Example: VOLUMES DIRFS v [path] List a directory on a selected volume. Example: DIRFS 0 \EFI\BOOT CAT v file Display a file as text. Example: CAT 0 \STARTUP.NSH HEXFILE v file Display a file as hex/ASCII. Example: HEXFILE 0 \EFI\BOOT\BOOTX64.EFI BOOT Inspect UEFI BootOrder / Boot#### information where available. Example: BOOT OS Best-effort installed operating-system detection. Example: OS ? or HELP Show monitor help. X Return to BASIC. NOTES ===== - BASIC source files are ASCII text with line numbers. - CREATEEXE / CREATEEFI embed the currently loaded BASIC program, not external data files. Keep BMPs, save files and other runtime assets beside the generated application as required by the program. - CREATEEXE and CREATEEFI are direct-mode commands and require a program to be loaded. - The UEFI build and Windows build share the language core, but a few startup and platform commands differ as documented above. - UEFI keyboard layout configuration is stored in THOREAU.CFG beside the EFI. Windows keyboard input remains native to Windows and ignores this file. - SYSTEM is portable BASIC source: it exits the Windows application or returns the UEFI application to its firmware/caller. - Thoreau BASIC is free to use. Support development: paypal.me/gatesofintegrity Website: https://thoreaubasic.com