• v1.3.7 4666ccb9ad

    SBC7 v1.3.7
    Some checks failed
    Release / build-rpm (push) Successful in 22m39s
    Release / build-deb (push) Successful in 15m11s
    Release / build-android (push) Successful in 22m37s
    Release / build-wasm (push) Failing after 8m2s
    Release / release (push) Has been skipped
    Stable

    bcox released this 2026-04-12 19:39:44 +00:00 | 13 commits to main since this release

    Signed by bcox
    GPG key ID: 1C87BFF7FAC89089

    If v1.2.0 was the release where SBC7 went from simulator to silicon, and
    v1.3.x is the release series where it became genuinely useful to live with,
    then v1.3.7 is the one where you can actually sit down at the thing, write
    a BASIC program, save it to disk, come back later, and load it again. That
    may sound modest. For a 7-bit computer, it is a complete arc. The gap
    between v1.3.1 and v1.3.7 spans six tagged versions that never made a
    public release, which means this notes entry covers rather a lot of ground.
    Here is all of it.

    (Why no v1.3.2 through v1.3.6? Because each one found something broken in
    the thing that had just shipped. Consider them the iterative part of
    "iterative development," now over.)

    Real-Time Clock

    The SBC7 has a clock now. The RTC peripheral (ports 48-55) tracks year,
    month, day, hour, minute, and second, seeded at reset from the host system's
    UTC clock in the emulator and from the MiSTer ARM HPS on hardware. There is
    no battery -- the clock does not survive power loss -- but it is accurate
    while it runs, it handles leap years correctly through 2127, and the boot
    banner now prints the date and time alongside the RAM and ROM sizes.

    The latch mechanism deserves a mention: writing CONTROL with LATCH=1
    snapshots all six time fields atomically, so a burst of IN instructions
    cannot catch a carry propagating from 23:59:59 to 00:00:00 in mid-read.
    This is the kind of detail that only becomes obvious after you have
    debugged the alternative.

    Gamepad Controller Port

    Two NES-style controller ports (ports 56-58) with a change-of-state
    interrupt at RST 5. D-pad, A, B, Select, and Start per controller; the ROM
    installs a bare RETI at the RST 5 vector, so programs can simply HALT and
    wake on any button event. On MiSTer, joystick_0 and joystick_1 from the HPS
    map to the two pads. In the emulator, player 1 is on the keyboard (arrows
    for D-pad, Z/X for A/B, A/S for Select/Start).

    Display Hardware: Color, Font, and Vertical Blanking

    This release effectively rebuilds the VGA output from the front panel
    inward.

    Indexed color per character cell. Every cell on the 64x24 display now
    has its own foreground and background color, selected from a 16-entry
    palette. The attribute byte format is compact: 3 bits of background (indices
    0-7) and 4 bits of foreground (indices 0-15), which gives brighter options
    for text while keeping dark backgrounds the sensible default. The palette
    itself lives in the color bank and is updated from the CPU's write side
    during vertical blanking.

    Per-channel gamma-corrected color expansion. The 7-bit native color
    encoding (2R 3G 2B) is expanded to 24-bit for display with different gamma
    curves per channel: R=1.6, G=1.5, B=1.4. The human eye does not perceive
    linear intensity as linear brightness, and the three channels do not agree
    on exactly how wrong the linear approximation is. The result is a more
    natural-looking palette, particularly in the mid-range colors that text
    actually lives in.

    Font data moved to ROM bank 7. The 128-glyph character set is now stored
    in a dedicated ROM bank rather than in the VGA hardware itself. The
    CHAR_BANK register (port 39) selects which bank feeds the character renderer,
    and the default points at ROM bank 7. This means custom fonts are possible
    by writing glyph data (128 glyphs x 14 rows) into any RAM bank and pointing
    port 39 at it.

    Vertical blanking interrupt at RST 4. The VGA controller fires RST 4
    at the start of each vblank, about 60 times per second. The ROM installs a
    bare RETI by default; programs that need synchronized palette updates or
    animation timing can install their own handler at &00:20. A boot-time RETI
    fix that had been shipped with a wrong opcode is also corrected here.

    Console control characters. The console driver gained cursor movement
    codes ($01-$06 for left/right/up/down), HOME ($0B), form-feed / clear-screen
    ($0C), foreground color select ($10-$1F for palette indices 0-15), and color
    swap/reset ($0E-$0F). Keyboard handling grew corresponding support for arrow
    keys, the Home key, Ctrl+digit color codes, and a properly timed ESC
    timeout. Scanline registers (ports 33-34) expose the current beam position
    and the vblank flag as readable values, useful for timing-sensitive code.

    ROM capability flags. The signature block at &7F:7F now carries a
    feature-flags byte: bit 0 = banking, bit 1 = disk, bit 2 = RTC, bit 3 =
    gamepad, bit 4 = color VGA. Programs that need to run on multiple ROM
    versions can read this byte to confirm what they are dealing with before
    trying to use features that may not be present.

    Filesystem: Full Read/Write

    S7FS now has a complete read/write story. The previous release had mount,
    open, read, close, directory listing, and free-space query. This release
    adds OPENW (open existing file for read/write), CREATE (create or truncate),
    WRITE, REMOVE, MKDIR, RMDIR, and SEEK -- syscalls 16 through 22. Timestamps
    are live: the ROM's _rtc_stamp helper reads the RTC and writes the
    creation timestamp when a file or directory is created, and the modification
    timestamp when a write-mode file is closed.

    The write driver is spread across ROM banks 4 and 5 to keep each bank within
    the 2 KB limit. Write operations go through the same FAT cluster-chain
    machinery as reads, with bank 8 used as scratch space during sector transfers.
    SEEK takes a 28-bit byte offset in the DSK_LBA registers, shared with the
    OPENW return value so appending is a single extra syscall.

    A race condition in the interrupt vector setup and a multi-cluster read bug
    in the filesystem driver are both fixed here.

    TinyBASIC: DIR, SAVE, and LOAD

    TinyBASIC now has a complete file I/O story at the BASIC level.

    DIR lists files with sizes and modification timestamps in long format,
    optionally targeting a subdirectory or a second drive. Directories are shown
    in brackets. Timestamps have quarter-hour resolution, which is the finest
    the RTC format stores.

    SAVE writes the current program to a named file on disk, in the same
    format that LIST produces. If the file already exists it is overwritten.

    LOAD reads a program back from disk, clearing whatever was in memory
    first. Files that span multiple disk clusters are handled transparently;
    the LOAD command walks the FAT chain as many times as needed. A related
    fix to the TIB (terminal input buffer) memory layout resolved an overlap
    with the B segment that had been quietly waiting to cause trouble in
    multi-cluster loads.

    Demos and Examples

    The factory disk now ships with an oscilloscope-style sine wave demo and
    palette display and logo display programs. The sine wave demo is a reasonable
    stress test for VBI-synchronized output and makes a good screensaver if you
    are the sort of person who runs a 7-bit computer unattended. The palette
    display shows all 16 palette entries with their expanded RGB values, which is
    useful when tuning color output on new hardware.

    Build System

    The justfile has been merged into the Makefile. The build system is now a
    single make invocation for all targets, including the examples, the
    language interpreters, and the cross-compilation workflow. Existing
    make-based habits are unaffected; just is no longer required.

    MiSTer Fixes

    H7X loading and disk I/O on MiSTer both received fixes during this cycle.
    The color pipeline was also corrected to match the emulator's output, so
    what you see in emu7 is what you see on the DE10-Nano.

    Downloads
  • v1.3.1 a13eaea3a2

    SBC7 v1.3.1
    All checks were successful
    Release / build-rpm (push) Successful in 13m24s
    Release / build-deb (push) Successful in 14m31s
    Release / build-android (push) Successful in 18m5s
    Release / build-wasm (push) Successful in 3m58s
    Release / release (push) Successful in 1m51s
    Stable

    bcox released this 2026-04-05 05:53:54 +00:00 | 76 commits to main since this release

    Signed by bcox
    GPG key ID: 1C87BFF7FAC89089

    If v1.2.0 was the release where SBC7 escaped the simulator and landed on real silicon, v1.3.1 is the one where it learned to think bigger than 16 kilobytes. The headline: bank-switched memory turns the SBC7 into a machine that can address up to 128KB of RAM and 16KB of ROM without changing the instruction set. Everything that worked before still works -- the default configuration reproduces the flat 16KB layout -- but now there is room to stretch.

    Along the way the assembler learned real arithmetic, the ROM grew a syscall mechanism, and quite a few things that were slightly broken got fixed. Some of them were more than slightly broken.

    Memory Banking

    The SBC7 address space is now divided into 8 slots of 2KB each. Each slot has a bank register (I/O ports 0-7) that selects which physical bank of RAM or ROM appears in that region. With up to 64 banks per slot, the theoretical ceiling is 128KB of RAM plus 16KB of ROM -- roughly eight times "more than anyone could possibly need" by 1980s standards.

    The bank registers default to an identity mapping (slot N = bank N), so existing software that never touches the bank registers sees exactly the same 16KB flat memory it always did. No migration required; your old H7X files just work.

    RAM bank count is now configurable across every platform: the MiSTer OSD menu, the Android emulator dialog, the web emulator URL parameter, and the RTL ram_bank_mask parameter. Pick your own adventure between "period-accurate austerity" and "I have BlockRAM to burn."

    Multi-Bank ROM

    The boot ROM has been reorganized into three 2KB banks:

    • Bank 0 (slot 7 at reset): boot code, ISRs, console driver, UART/timer drivers, jump table, and the new FARCALL/EXTCALL dispatchers.
    • Bank 1: the interactive monitor (line editor, hex commands, H7X loader), mapped into slot 1 on demand.
    • Bank 2: extended syscall handlers, mapped into slot 2 by the EXTCALL dispatcher.

    Moving the monitor out of bank 0 freed approximately 660 bytes -- which in a 2KB ROM is practically a luxury apartment. Console output functions are bank-aware: they write to the VGA screen bank regardless of how the user has remapped slot 6, which means double-buffering is now possible without corrupting your terminal output.

    A bank-safe interrupt trampoline ensures that user code can remap slot 7 (the ROM slot) for its own purposes without breaking interrupt dispatch. The CPU still vectors into slot 7, but the trampoline restores the ROM bank, services the interrupt, and puts the user's bank back.

    FARCALL and EXTCALL

    Two new calling mechanisms for banked code:

    FARCALL is a reentrant bank-switching indirect call. Point a register pair at a far-address structure (target bank + address), invoke the CALLFAR macro, and the ROM handles the bank switch, the call, and the restore. It is fully reentrant, so interrupts and nested far-calls work correctly.

    EXTCALL (via RST 7) is a table-driven syscall dispatcher. The byte following the RST 7 instruction is the syscall number; the ROM maps bank 2 into slot 2, looks up the handler, calls it, and unmaps. Four initial syscalls ship in this release:

    Syscall Function
    PRT7DEC Print 7-bit value in decimal
    PRT7HEX Print 7-bit value in hex
    PRT14DEC Print 14-bit value in decimal
    PRT14HEX Print 14-bit value in hex

    The mechanism is extensible -- adding new syscalls is a matter of adding entries to the dispatch table in bank 2.

    Assembler Expression System

    The assembler's expression parser has been substantially overhauled. Where previously you had to pre-compute constants and scatter magic numbers through your source, you can now write full arithmetic expressions anywhere a value is expected: addition, subtraction, multiplication, division, modulo, shifts, bitwise operations, unary minus and complement, parentheses for grouping, and $ for the current program counter. Labels and numeric literals are fully interchangeable in expressions.

    New multi-bank directives (.bank, .slots, .entrypoint) let a single source file produce multi-bank H7X2 output. The assembler also now treats .inc files as implicitly pragma-once (no more include guards), and checks for reserved name conflicts at definition time instead of letting you discover them at link time or, worse, at runtime.

    H7X2 Object Format

    The H7X format gains a bank-aware successor. H7X2 files carry per-record bank tags so loaders know which physical bank each chunk belongs in. All loaders -- emu7, MiSTer, disasm7, and the ROM monitor -- have been updated to handle both H7X and H7X2 transparently.

    ROM Signature Block

    The top 8 bytes of ROM (&7F:78--&7F:7F) now contain a machine-readable signature: the ASCII string "SBC7", a three-part version number (major.minor.patch), and a feature-flags byte. Bit 0 of the flags byte indicates banking support. Software can probe this to determine ROM capabilities at runtime instead of guessing.

    Breaking Changes

    The ROM jump table has moved. All jump table entry addresses have changed in this release. If you have code that calls ROM routines by hardcoded address rather than by symbol, it will break. Reassemble against the new ROM symbols and you are fine. The assembler expression system makes this painless -- use the symbolic names, and the assembler will sort out the addresses for you.

    This is the cost of reorganizing the ROM for banking. We considered maintaining backward compatibility and decided it was not worth the contortion; better to break cleanly once than to accumulate thunks forever.

    Tooling

    • VS Code extension: The vsix package was missing its node_modules directory, which is the extension-packaging equivalent of shipping a car without an engine. Fixed. Also: a restart command, extensionKind: workspace for remote development, and TextMate grammar updates for doc comments and bank directives.
    • lsp7: Macro invocations now support hover and go-to-definition. The .bank, .slots, and .entrypoint directives have proper documentation. False errors on macro parameter references are gone (fixes #1).
    • dap7: Step-over now handles all opcodes correctly, and the debugger variables pane includes a bank register scope so you can see which banks are mapped where.
    • SBC7 font: The Panose classification now correctly identifies the font as monospaced, so VS Code will actually offer it in the font picker instead of hiding it behind a bushel.

    Emulator Performance

    Three changes that add up to noticeably smoother emulation on Linux:

    1. Batched UART stdout flush -- previously every byte was a separate syscall inside a mutex lock. Now they are batched per frame.
    2. Spin-yield throttling replaces thread::sleep(500us), which on Linux had 1--4ms actual granularity. The emulator now hits its target frame rate instead of overshooting by 2--8x.
    3. GUI snapshot takes a single mutex lock per frame instead of 3--4, and no lock is held during rendering.

    MiSTer FPGA Fixes

    • Quartus 17 Lite compatibility: An unpacked array port in bank_regs has been flattened to a packed bus. Quartus Lite does not support unpacked arrays on module ports, and it expresses its displeasure by refusing to synthesize.
    • OSD menu: CONF_STR updated to bracket notation; J/jn entries moved to end of string per MiSTer framework requirements.
    • Programmer's switch reliability: The interrupt pulse was 1 clock wide, and the CPU's clock-enable divider missed it roughly 44% of the time. Stretched to 8 clocks. The USER button is now wired to the programmer's switch as well, and the default gamepad binding has moved from A to left shoulder -- because "accidentally triggering the debugger mid-game" is only fun in stories you tell later.

    Signing and Verification

    Release artifacts (RPM, deb, tarballs) are now GPG-signed. Each release includes detached .asc signatures and a signed SHA256SUMS file. Verification instructions and the public key are in the repository. Closes #7.

    Documentation

    • H7X object file format specification.
    • MMIO range &60:00--&63:7F formally documented as reserved (fixes #14).
    • Doc comments (;;) added to every ROM label, so lsp7 can show you what a routine does when you hover over it.
    • Nine documentation inconsistencies across RTL and docs fixed.
    • All assembly sources formatted with fmt7.

    Bug Fixes

    • Boot sequence: UART0 initialization moved earlier in the boot path so serial output works before the banner prints. A trailing space in the banner text, stale-flags bugs in the decimal print routines, and a register corruption in the 14-bit subtract helper (which caused PRT14DEC to loop forever) are all fixed.
    • ROM alignment and init banner text corrections.
    Downloads
  • v1.2.0 d753ec9685

    SBC7 v1.2.0
    All checks were successful
    Release / build-rpm (push) Successful in 13m21s
    Release / build-deb (push) Successful in 14m8s
    Release / build-android (push) Successful in 17m4s
    Release / build-wasm (push) Successful in 3m48s
    Release / release (push) Successful (Homebrew tap step soft-failed, release published)
    Stable

    bcox released this 2026-03-29 05:55:32 +00:00 | 119 commits to main since this release

    If v1.0.0 was the release where SBC7 became a computer, v1.2.0 is the
    one where it escaped from the simulator and started living on actual
    silicon. The headline: SBC7 now runs on the MiSTer FPGA platform, on
    real hardware, with real VGA output and a real keyboard. Along the way
    it picked up two new programming languages, a debugger, a web
    emulator, and several CPU bug fixes that turned out to matter quite a
    lot once the gates were no longer imaginary.

    (Why no v1.1.0? Because the bugs we found on hardware were
    load-bearing enough that we wanted them fixed before anyone else hit
    them. Consider the intervening commits a dress rehearsal.)

    MiSTer FPGA Core

    SBC7 runs on the DE10-Nano. Plug it in, pick it from the menu, and
    you are looking at the monitor prompt on a real screen driven by real
    flip-flops.

    • VGA output through the MiSTer HDMI scaler. The native 7-bit
      color (2R+3G+2B) is expanded to 24-bit, so your television does not
      need to know it is only getting 128 colors.
    • PS/2 keyboard input via a serial bridge. Typed characters,
      Backspace, Delete, Enter, and Ctrl+letter all work as expected.
      Extended scancodes are filtered to a whitelist so your GUI key does
      not type a phantom q.
    • UART1 routed to the MiSTer serial port, so you can connect an
      external terminal for a second channel.
    • H7X file loading from the OSD. Open the File menu, pick a
      .H7X file, and type G at the monitor prompt to run it. This is
      how you load TinyBASIC, TinyLISP, and anything else that does not
      fit in ROM.
    • OSD controls: Reset, Programmer's Switch, and Power Cycle (which
      clears all RAM -- the FPGA equivalent of pulling the plug).
    • Joystick mapping: A = Programmer's Switch, Start = Reset,
      Select = Power Cycle. For when you want to debug with a gamepad,
      which is a sentence nobody expected to write.
    • Aspect ratio selectable in the OSD for the display purists.

    New Programming Languages

    SBC7 now ships with three high-level languages:

    • TinyBASIC -- a line-numbered BASIC interpreter. PRINT, INPUT,
      IF/THEN, GOTO, GOSUB, FOR/NEXT, and the rest of the 1975 starter
      kit. If you learned to program on a microcomputer, this will feel
      like coming home.
    • TinyLISP -- a Lisp interpreter with garbage collection, lambda,
      define, cons/car/cdr, and arithmetic. Seven bits are enough for
      anyone who wants to argue about parentheses.
    • Both join TinyFORTH, which shipped in v1.0.0 and remains as
      stack-happy as ever.

    CPU Bug Fixes

    These were found the hard way: by running real programs on real
    hardware and watching them do the wrong thing.

    • ST14 [addr] was broken. The DECODE2 condition ir[1] == 0
      excluded ST14 (opcode 0x1E), which meant the CPU skipped fetching
      the address bytes and jumped straight to EXECUTE. The write went to
      whatever garbage was left on the address bus, cheerfully corrupting
      memory. Every program that stores a 14-bit value to an address --
      which is to say every nontrivial program -- hit this. TinyBASIC,
      TinyFORTH, and TinyLISP all failed on hardware until this was
      found. It worked perfectly in the emulator, because of course it
      did.
    • INC A / DEC A set the N flag from the wrong value. The negative
      flag was being computed from the accumulator before the
      increment or decrement, not after. Subtle, but it meant branches
      after INC/DEC could go the wrong way.
    • Synchronous memory latency. A new MEM_WAIT state in the CPU FSM
      gives synchronous RAM time to deliver its data before the CPU reads
      the bus. Without it, back-to-back clock enables could read stale
      values. A companion hold-off cycle in the clock divider guarantees
      this cannot happen.

    MiSTer OSD Control Fixes

    • Programmer's Switch changed from level-sensitive to
      edge-detect with a pulse counter. Previously it only worked on odd
      clicks, because the T1 toggle would set on one press and clear on
      the next.
    • Power Cycle changed from R2 (which triggers the MiSTer
      framework's own RESET and raced with the RAM-clear FSM) to T2
      (toggle only), so the core controls its own destiny.
    • Extended key filtering tightened to a whitelist of known
      scancodes (Delete, Keypad Enter) instead of passing everything
      through. Left GUI was arriving as q, which is only charming the
      first time.

    Emulator and Tooling

    • dap7 -- a Debug Adapter Protocol server for VS Code.
      Breakpoints, single-stepping, register and memory inspection, and a
      live VGA display, all from the comfort of your editor.
    • Android emulator -- SBC7 in your pocket. The retrocomputing
      community has wanted this since approximately never, but here it is.
    • WASM web emulator -- SBC7 in your browser, no install required.
      The sbc7.js module is reusable for embedding in your own pages.
    • Web font generation from the built-in VGA character ROM, so the
      SBC7 aesthetic can follow you onto the web.
    • fmt7 assembly formatter and lsp7 language server, plus a
      VS Code extension bundling syntax highlighting and LSP
      integration. (These shipped in the unpublished v1.0.1 cycle and are
      now formally released.)

    ROM and Assembly

    • Named constants replace magic numbers across all assembly
      sources. The code now reads like documentation instead of a hex
      dump.
    • Monitor input buffer moved from I/O space to RAM, freeing I/O
      addresses for hardware that actually needs them.
    • Console output documentation and a character set graphic added to
      the docs.

    Packaging and CI

    • Cross-compilation replaces emulated ARM containers -- aarch64
      builds are now fast instead of merely possible.
    • Unified versioning across all Cargo.toml files, package.json,
      deb/rpm packages, and language version strings. One version number
      to rule them all.
    • Homebrew tap support (brew install bcox/sbc7/sbc7).
    • Proper runtime dependencies declared in deb and rpm packages.
    • Forgejo release creation with automated MiSTer zip upload.
    • CC0-1.0 license applied to the project.

    Why 1.2.0?

    Because the computer is no longer a simulation, the CPU had bugs that
    only showed up on real hardware, we added two programming languages,
    and incrementing the minor version once did not seem like nearly
    enough.

    Downloads
  • v1.0.0 d77dad8c52

    SBC7 v1.0.0
    All checks were successful
    Release / build (push) Successful in 10m56s
    Stable

    bcox released this 2026-03-23 13:06:36 +00:00 | 181 commits to main since this release

    SBC7 release v1.0.0

    Downloads
  • v0.9.1 05a308d568

    SBC7 v0.9.1
    All checks were successful
    Release / build (push) Successful in 11m20s
    Stable

    bcox released this 2026-03-22 21:30:23 +00:00 | 195 commits to main since this release

    SBC7 release v0.9.1

    Downloads
  • 0.9.0 8b1414c204

    0.9.0 Stable

    bcox released this 2026-03-22 05:54:43 +00:00 | 203 commits to main since this release

    This is a first-draft release. Everything works (as far as I can tell), but there are gaps before I can call it complete.

    Downloads