Skip to content

UltimateBasic 64 1.6.6

Choose a tag to compare

@zstarczali zstarczali released this 18 Oct 12:31
· 8 commits to main since this release
3da3c2c

ltimate Basic v1.6.6 – Release Notes

2026-10-18 – Unreleased (after 1.6.6)

New

  • option strings n [, m]: a computed string variable holds up to n
    characters (1-255, default 80), a string-array element up to m
    (default 31). Each variable keeps its own buffer.
  • Compile-time warnings: a byte variable that gets a constant it
    cannot hold (b = 300, b = a + 1000) is reported with its line.
    Warnings never stop the build.
  • With --basic-print, STR$ gives the C64 BASIC text for every number
    (" 7", "-42", " 3.5"); without it a byte keeps "007".
  • Struct types: field defaults (var hp: word = 100 - the array's
    contents at program start), nested struct fields (e[i].pos.x),
    fixed-length string fields (var name: string * 20), struct
    parameters (sub heal(p AS TEntity) ... heal(e[i])), and the QBasic
    form TYPE ... name AS type ... END TYPE. A struct element can be at
    most 256 bytes (a compile error says so).
    Changed
  • In a SUB / FUNCTION closed by END SUB / END FUNCTION, END alone on
    its line ends the program, as in QBasic (also inside IF ... END IF).
    Blocks in such routines are closed QBasic-style.
    Fixed
  • / with a WORD, INTEGER or negative divisor used only the low byte
    of the divisor: -700 / -7 gave 0, 50000 / (v + 0) was wrong. It is
    a 16-bit division now, truncated toward zero.
  • END and BYE inside a sub or function returned to the caller
    instead of ending the program.
  • A variable index into a struct array was multiplied in 8 bits, so
    elements beyond byte offset 255 were read and written wrongly.
  • Word struct fields were cut to 8 bits inside expressions, and
    word + x / word - x dropped the high byte of a 16-bit x (a word
    array element, a word function).

2026-10-17 – Release 1.6.6: PRINT USING, string order, floats

New

  • PRINT USING "format"; values (QBasic subset): numeric fields with

    digits, . point, , thousands separators, a leading + (always a

    sign) and a trailing - (sign after the number); a number that
    does not fit is printed with a % in front. String fields & (whole
    string), ! (first character) and \ \ (as wide as the field);
    _ prints the next character as it is. Values cycle through the
    fields; a trailing ; or , keeps the cursor on the line. The format
    must be a string literal.
  • Strings can be ordered: < > <= >= compare in PETSCII order, a
    shorter string first when it starts the other ("AB" < "ABC").
  • RND as a floating-point number: in a statement that computes in
    floating point, rnd / rnd() is 0 <= x < 1 (d = rnd, x = rnd() * 6).
    rnd(n) and integer statements keep the 0-255 / 0..n-1 generator.
  • MOD with a SINGLE / DOUBLE operand works in floating point, like
    VB / C fmod: 7.5 mod 2 = 1.5, -7.5 mod 2 = -1.5; x mod 0 = x.
  • Floating point in IRQ / NMI handlers: a handler sub (irq, nmi,
    cia_timer) that uses SINGLE / DOUBLE saves and restores the
    runtime state, so it no longer disturbs the main program. Handlers
    without floating point cost nothing extra.
  • --basic-print (or a line "option basic print" in the program):
    C64 BASIC PRINT spacing - numbers print with a leading space (or
    their minus sign) and a trailing space (print 5 gives " 5 "), a ,
    between items moves to the next 10-column zone, a trailing , keeps
    the line. Without it the output is unchanged.
    Changed
  • Programs carry only the floating-point routines they use: a small
    program with + * and PRINT went from 4603 to 2293 bytes,
    examples/float_demo.ub from 6319 to 5660.
  • MOD with a WORD or INTEGER operand is a real 16-bit remainder with
    the sign of the dividend, like QBasic: -7 mod 3 = -1, 7 mod -3 = 1,
    (w + 5) mod 7 is no longer cut to 8 bits.
  • SHR of an INTEGER is an arithmetic shift: -8 shr 1 = -4. WORD and
    byte SHR stay logical.
    Fixed
  • A literal from 32768 to 65535 in a floating-point statement was
    read as a negative 16-bit pattern: d = 40000 gave -25536. It keeps
    its value now; integer statements are unchanged.