Repository navigation
UltimateBasic 64 1.6.0
Ultimate Basic v1.6.0 – Release Notes
2026-10-03 – Release 1.6.0: optimised 6502 code generation
Performance
- Conditions (if / while / until / select) compile to CMP + branch
instead of materialising a 0/1 value and testing it again
(if x == 10: 24 -> 9 bytes).x > nbecomesx >= n+1; and / or of
comparisons short-circuit when the right side is side-effect free;
while loops are rotated (test at the bottom); select compares the
variable in place. - Constants and byte variables are used directly as operands
(ADC #n, CMP zp) instead of being staged in scratch zero page; poke to a
constant or word address stores directly; identity operations vanish. *by a constant: shifts / shift-add (x * 8 -> 3x ASL); otherwise a
shift-add loop of at most 8 rounds (the old repeated-addition loop
needed ~16 cycles per unit of the multiplier)./andmodby a power of two: LSR / AND #(n-1); otherwise an 8-round
shift-subtract loop (the old loop ran once per unit of the quotient).- x = x +/- 1|2 -> INC / DEC (word: 16-bit INC / DEC for +/-1).
- Arrays with a variable index use base,Y addressing instead of a
zero-page pointer. - for loops are rotated (no JMP per iteration); constant limits / steps
are immediates and use no zero page. - A-register reuse: the leading LDA of a statement is skipped when it
reloads the value the previous statement just stored.
Fixes
- Division by zero used to hang: now x / 0 = 255 and x mod 0 = x.
for i = 0 to 255looped forever; the step now detects the 8-bit
wrap-around in both directions, so the loop runs 256 times and stops.
Tests
- Full 6502 emulator for tests (tests/common/cpu6502.rs), semantic tests
that run compiled programs (tests/codegen_semantics.rs), code-shape /
cycle tests (tests/codegen_opt.rs) and an ignored differential fuzzer
against a reference compiler (tests/differential_fuzz.rs).
2026-09-26 – chain: load and start another program
New language elements
- Added
chain "FILE" [, device]: loads another program to its own load
address (normally $0801, right over the running program) and RUNs it, as
if LOAD"FILE",8,1 and RUN had been typed. For boot / title programs.
A 46-byte position-independent loader and the file name (1-16
characters) are copied to the cassette buffer $033C. Before the load the
I/O is reset (VIC IRQs off, SID volume 0, IOINIT, RESTOR, $01 = $37);
after it the end-of-program pointer $2D/$2E is set, BASIC is
re-initialised ($E453, $E3BF - a self-extracting cruncher such as
Exomizer sfx may have used BASIC's zero page) and the program is RUN
($A659, $A7AE). Without a device the drive the program came from ($BA)
is used, else drive 8. If the file cannot be loaded, the program
continues with the statement afterchain.
Fixes
load: the secondary address was swapped.load "FILE"used secondary
0 with X/Y = 0 and loaded the file to $0000;load "FILE", addrused
secondary 1 and ignoredaddr. Nowload "FILE"loads to the file's own
address (secondary 1) andload "FILE", addrtoaddr(secondary 0).--d64: directory entries were written 30 bytes apart instead of 32, so
every file after the first had a broken entry (e.g.--add data.prg
showed up as a garbled name and could not be loaded). Also fixed: disk ID
and DOS type were at the wrong BAM offsets; file data only used tracks
1-17 (a larger disk crashed the build instead of reporting it); sectors
are now allocated like the 1541 DOS does (tracks 17->1, then 19->35,
interleave 10). A full disk is reported as "D64 error: disk full ...".
New tests: tests/d64_tests.rs reads the image back (BAM, directory,
sector chains) and compares every file.
2026-09-25 – Initialised arrays
New language elements
- Added
data <array>: v, v, ...: fills a declaredarray/array_word
with constant values. Further lines continue where the previous one
stopped; word arrays take 16-bit values (stored lo, hi). The values are
stored after the code and copied into the array once at program start
(right after the arrays are zeroed), so the table is writable and indexed
like any other array (sinus[i]). These lines do not affectread.
An undeclared name or more values than the array holds is a compile-time
error. This is what the Visual Assembler Curve Editor's "Export to
UltimateBasic" and "Export UltimateBasic demo" generate.