Skip to content

v2026.04.19-dev

Pre-release
Pre-release

Choose a tag to compare

@github-actions github-actions released this 19 Apr 18:52
· 81 commits to main since this release

BlueSCSI-v2 Release Notes — v2026.04.19-dev (prerelease)

This release brings a new build system, a much simpler firmware update flow, broader SCSI command coverage, and a long list of fixes across CD-ROM, CD audio, tape, DaynaPORT, initiator mode, and the Ultra/Ultra Wide hardware.

Important

Users should use the uf2 update method for this release to get the latest boot loader improvements.

New Features

Firmware update & logging

  • Universal firmware ZIPfirmware_update() scans the SD card root for BlueSCSI_v*.zip, extracts the target-specific .bin, and hands it to the bootloader. Same ZIP works for every board. (cb61c37@erichelgeson)
  • Shared bootloader log — a 2 KB NOLOAD region at the top of RAM survives the reset from bootloader into main firmware, so firmware-update log lines are no longer lost. (cb61c37@erichelgeson)
  • lastlog.txt — previous session's log.txt is renamed to lastlog.txt on first boot before the new log starts, so the prior run is always recoverable. (cb61c37@erichelgeson)

BlueSCSI Toolbox

  • SET_WORKING_DIR (subcommand 0x02) — Toolbox clients can point file operations at the SD card root (or any directory) for firmware uploads and file management. (24bbc20@erichelgeson)
  • GET_WORKING_DIR (subcommand 0x03) — returns the currently effective directory as a null-terminated string so clients can display it. (25fdaa6@erichelgeson)
  • New capability flag CAP_SET_WORKING_DIR (bit 2, 0x04) lets clients detect support. (24bbc20, 25fdaa6@erichelgeson)

SCSI commands

  • READ(12)/WRITE(12), READ(16)/WRITE(16), READ CAPACITY(16) — proper dispatch for the 12- and 16-byte disk commands. (c4f8a73@reinauer)
  • VERIFY(10/12/16) — medium scan (BYTCHK=0) and byte-compare (BYTCHK=1) both implemented. (c4f8a73@reinauer)
  • WRITE AND VERIFY(10/12/16) — data is written and re-read to confirm the sectors match. (c4f8a73@reinauer)
  • MODE SENSE Verify Error Recovery page (07h) — optional SCSI-2 §9.3.3.8 page 07h (page length 0Ah, verify retry count 1, other fields zero), returned only in SCSI-2 mode. Some vintage OSes expect this page when requesting all pages (0x3F). (318a1c1@erichelgeson)
  • MODE SENSE Notch and Partition page (0Ch) — optional SCSI-2 §9.3.3.5 page 0Ch with all fields zero, indicating a non-notched drive. Returned only for SCSI-2 direct-access devices (excluded from optical and sequential). (1e1a1a5@erichelgeson)
  • Trace log coverage for new commands — SCSI trace output shows names for Read16, Write16, Verify16, WriteVerify16, ServiceActionIn16, Write12, Verify12, WriteVerify12. (8bcc3c8@PetteriAimonen)

Initiator mode

  • Fixed VHD image output — with InitiatorVHD=1 in bluescsi.ini, imaged drives are saved as Microsoft Fixed VHD files with a conforming 512-byte footer, directly mountable in Windows/QEMU/VirtualBox. (e7ebcab@erichelgeson)

Diagnostics

  • Hardware stack overflow protection (RP2350)MSPLIM is set on both cores with 32 bytes of exception-frame headroom; overflows now crash-dump instead of corrupting RAM. (20823c9@erichelgeson)
  • Enhanced hardfault logging — CFSR/HFSR/MMFAR/BFAR are decoded into human-readable fault conditions on RP2350. (20823c9@erichelgeson)
  • SD card OID decoded in log — the card identification line now prints the 2-byte OID as ASCII alongside the resolved manufacturer name, making it easier to identify the exact card in a user's log. (ad1494a@erichelgeson)

Bug Fixes

CD-ROM & CD audio

  • SPDIF crash on multi-BIN CUE sheets (#353)selectImageFile() no longer allocates FastSeek for metadata-only opens, and doReadTOC / doReadFullTOC / doReadTrackInformation stop audio before switching BIN files. (8b06063@erichelgeson)
  • SPDIF reported wrong LBA on READ SUB-CHANNEL / PLAY AUDIO (#353) — the audio position math now accounts for each track's file_offset and data_start, so multi-BIN CUEs and tracks with unstored PREGAP report correct LBAs. (a2835e6@erichelgeson)
  • SPDIF PLAY AUDIO seek wrong for tracks with PREGAPdoPlayAudio now uses data_start instead of track_start, fixing audio on discs like Tatsujin Ou (FM Towns) where Track 2 has PREGAP 00:02:00. (b2f2fda@erichelgeson)
  • Track boundary correctness — added cdrom_track_end_lba so READ CD splits transfers at track boundaries on multi-track discs instead of conflating BIN file size with track extent. (8f7e389@reinauer / @erichelgeson)
  • READ HEADER (0x44) — parses LBA from CDB bytes 2-5 instead of always returning data for LBA 0; audio-track mode is written to the correct variable. (8f7e389@reinauer / @erichelgeson)
  • READ CD I/O errorsseek() / read() failures now return CHECK CONDITION with MEDIUM ERROR / CIRC UNRECOVERED ERROR instead of silently returning corrupt data. (8f7e389@reinauer / @erichelgeson)
  • WRITE AND VERIFY (0x2E) — returns ILLEGAL REQUEST on CD-ROM instead of silently performing an unverified write. (8f7e389@reinauer / @erichelgeson)
  • getTrackFromLBA() without track_end_lba — corrected fallback for discs where the track end isn't known up-front. (389ce31@PetteriAimonen)
  • Stale cdrom_track_end_lba across image changes — reset on CUE sheet reload and folder-based CD init. (b250f35@erichelgeson)
  • Audio playback after CD change — stale cached trackinfo from the previous disc no longer causes read errors on the next disc; doSeek's audio call is guarded by bin_container.isOpen(). (b2ea073@morio)
  • Audio with multiple CD-ROM drives — new play command stops all audio (id=0xFF) and reloads the cue when the audio owner changes; audio_last_status indexes by owner, not by passed id. Bus reset also stops audio. Applied to both I2S and SPDIF. (87cbe5b@morio)
  • Audio array sizing for wide SCSI — 8-entry audio arrays now sized for 16-target wide boards; ID masks corrected. (5611fc4@morio)
  • Eject wrapping on multi-BIN/CUE — eject button now compares the container directory name instead of the inner BIN filename, so multi-BIN discs wrap back to the first image. (30ed064@morio)

Tape drive

  • SPACE now uses absolute position and signed 24-bit count — per SCSI-2 §10.2.11, SPACE is relative to the current position and the count is two's-complement (negative = reverse). Previous code used an unsigned count and set tape_pos = count (absolute). (79432e3@erichelgeson)
  • Variable-block READ underlength/overlength conditions — conditions were swapped. Per SCSI-2 §10.2.4 overlength is not an error; only underlength errors, and only when SILI is clear. (e4d81d4@erichelgeson)
  • READ BLOCK LIMITS bad LSB bytedata[5] duplicated data[4], reporting min=0x0202 for 512-byte blocks. (7bdd5a8@erichelgeson)
  • SPACE CDB byte extraction — was reading a 32-bit count across CDB[2-5] including the control byte. Now a proper 24-bit extract from CDB[2-4]. (7bdd5a8@erichelgeson)
  • Variable-block READ/WRITE with transfer length 0 — per SCSI-2 §10.2.4 and §10.2.14, a zero transfer length is explicitly "not considered an error"; no data shall be transferred and the tape position is unchanged. (b6ed6b1@erichelgeson)

DaynaPORT / network

  • AppleTalk slow under Virtual Memory on System 7 (#346) — multi-packet READ(6) is now gated on CDB byte 5 bit 6 (polled mode = 1 packet, blind mode = batched). Bus hold time stays short when the host's VM pager also needs bus access. Transfer size now respects the host's allocation length in CDB[3-4]. (7c20579@erichelgeson)
  • Global INI strings no longer break DaynaPORT/AmigaWiFi — vendor/product/revision set under [SCSI] in bluescsi.ini are skipped for network devices, which require specific IDs for their drivers. Per-device [SCSIn] overrides still apply. (9f795a7@morio)
  • WiFi (DaynaPORT) restored on CMake build — after the PlatformIO → CMake migration, CYW43 compiled from source needs PICO_CYW43_SUPPORTED=1, CYW43_WARN=//, cyw43_arch_poll() in platform_poll(), and our own cyw43_tcpip_link_status(). Tested on Pico 1W / Pico 2W with open and WPA2 networks. (4af22d7@erichelgeson)
  • Ultra / Ultra Wide WiFi with GCC 14 — custom board headers and pico-sdk-internal v2.2.0-UltraSupport-rel2 work around a pico-sdk write-buffer ordering bug on Cortex-M33 that broke CYW43 SPI on Ultra hardware. (b0e1a4e, 79df606@erichelgeson)

Initiator mode

  • USB MSC initiator no longer overrides hardware switch — when the SD card is absent, the hardware initiator switch setting is respected instead of being forced by USB MSC. (290f513@erichelgeson)
  • Ultra initiator mode on some drives — timing tweak so initiator mode works against drives that were previously flaky on Ultra hardware. (2007324@androda)

SCSI core

  • WRITE to read-only media returns DATA_PROTECT — per SCSI-2 §9.1.12 and Table 69, WRITE PROTECTED (ASC 0x2700) pairs with sense key DATA_PROTECT (0x07), not ILLEGAL_REQUEST (0x05). Some hosts branch on the sense key to distinguish "bad CDB" from "media write-protected" and retried incorrectly. (b9bd4af@erichelgeson)
  • REQUEST SENSE Valid bit only when Information field is meaningful — Valid (0x80) was set unconditionally and the Information field was always populated with transfer.lba, even for sense keys like ILLEGAL_REQUEST or UNIT_ATTENTION where no block address applies. Per SPC-2 §7.20, only MEDIUM_ERROR, HARDWARE_ERROR, and ABORTED_COMMAND now report Valid=1 with the LBA; other keys return error code 0x70 with a zeroed Information field. (f7feb1d@erichelgeson)
  • MODE SENSE reserved CDB byte 3 — non-zero values in the reserved byte (SPC-3+ SUBPAGE CODE) are now rejected per SCSI-2 §8.2.10/8.2.11 and SPC-2 §7.8/7.9, returning CHECK CONDITION / ILLEGAL REQUEST / INVALID FIELD IN CDB. (f914e04@erichelgeson)
  • Packed scsiId field safetyS2S_TargetCfg::scsiId packs ID in bits 0-2 and the TARGET_ENABLED flag in bit 7. Introduced typed accessors and fixed a prefetch cache comparison that was missing the mask, causing bogus invalidations when the enabled flag differed between operands. (826b981@erichelgeson)
  • scsiLogDataOut NULL buffer crash — data-out trace logging no longer crashes when the buffer pointer is NULL. (beaada1@morio)
  • Stack overflow returning to IMG0 — refactor avoids the recursion that overflowed the stack when cycling back to the first image. (49b319f@NT2MKU)
  • Stack overflow during image init (RP2350) — stack sized and laid out to fit Audio SPDIF's peak usage. (887508b, 1851c05@erichelgeson)
  • ROM drive flash-write crash on Ultra with WiFi — core1 mutex now protects flash writes during ROM drive loading so WiFi code on the other core can't be interrupted mid-flash. (15b7d10@PetteriAimonen)
  • delay_ns() sub-microsecond accuracy — was rounding up by a full microsecond, making RST glitch-filter timing up to ~2× too long. Now cycle-accurate. (b2a0584@erichelgeson)

Timing / sync negotiation

  • Sync rate alignment with target timing — synthesize the sync offer from the actual PIO transfer period so we advertise rates we can sustain. (4df54b5@reinauer)
  • Custom timing overrides hardened — INI timing overrides are bounds-checked and validated before applying, so partial bad configs no longer take effect. (830acb4@reinauer / @erichelgeson)
  • Lowered DMA read-pacer floors — faster sync: RP2350 14→13 cycles (~19 MB/s at 252 MHz), RP2040 18→15 cycles (~16.7 MB/s at 252 MHz). RP2040 18 had caused a 16→10 MB/s regression. (18283f0@erichelgeson)
  • Overclocking suggestion threshold — only logged when sync speed is 10 MB/s, not at lower speeds. (f534dbf@erichelgeson)
  • TurboMax clk_hz corrected — 252 MHz → 250 MHz (an accidental change in 75d0b6b0). (74c61a0@erichelgeson)

SD card & storage

  • SD card hot-plug with multi-BIN/CUEscsiDiskCloseSDCardImages() now closes bin_container and resets image_directory, so "Already found an image directory, skipping..." no longer prevents images from loading after re-insertion. (e44445d@morio)
  • Geometry warning suppressed for >8 GB images — no more spurious C/H/S warnings on large disks. (f301988@erichelgeson)

BlueSCSI Toolbox

  • Shared dir creation before file opsonSendFilePrep, doCountFiles, and onListFiles now create the shared directory if missing and return CHECK CONDITION on failure, instead of silently writing to the SD root or continuing with no directory open. (581c6c7@erichelgeson)

Bootloader & boot

  • RP2350 bootloader XIP cache guard — corrected a wrong #define name that left the cache unguarded during bootloader flash operations. (455510a@erichelgeson)
  • Bootloader log replay garbagelog_raw(buffer, len) was resolving to a template that printed the buffer as a string plus the length as hex (e.g. .0x000000A2) instead of a fixed-length copy. (ecb2ee5@erichelgeson)
  • USB serial log missing on RP2040 — the CMake migration dropped Arduino-Pico's background USB timer, starving CDC enumeration during setup. A 1 ms repeating timer alarm now pends a software IRQ that calls tud_task() under __usb_mutex. Early-boot logs reach the serial console again. (7655af0@erichelgeson)
  • Build timestamp showed "Jan 1 1980" — Nix's SOURCE_DATE_EPOCH was feeding __DATE__/__TIME__ the epoch. Now unset in the dev shell so firmware reports the real build time. (30ba8b1@erichelgeson)

Improvements

  • Faster CD sector reads — when skip_begin == 0 (contiguous layout) we seek once before the transfer loop instead of per sector. (0d9ded1@reinauer / @erichelgeson)
  • Quieter Vdd warnings — voltage-drop warnings deferred by ~1 s, suppressing noise during power-off and brief dips. (1b9bcc4@erichelgeson)
  • C++ exception bloat eliminated — 31.8 KB of unused C++ exception tables trimmed from the RP2040 image, plus improved flash/RAM symbol placement. (81738d2@erichelgeson)
  • Static stack usage analysis in CI — build pipeline now flags functions with large stack frames before they reach hardware. (2aa6130@erichelgeson)
  • Application code built at -O2 — switched from -Os for better throughput on hot paths. (cb4da9e@erichelgeson)

Build & infrastructure (user-visible)

  • CMake + Nix flake build system — replaces PlatformIO. ./build.sh in a nix develop shell builds any target. See BUILDING.md. (1c41f99@erichelgeson)
  • Release / pre-release tag handling — firmware build workflow now distinguishes release vs. pre-release tags for cleaner release management. (315b208@erichelgeson)
  • minGlue.h include guard — adds #ifndef MINGLUE_H so test stubs can shadow the header; unblocks x86 unit testing for minIni glue. (4a3a15e@erichelgeson)
  • macOS build support — flake and build scripts updated so macOS hosts can build the firmware. (8d1794b@erichelgeson)
  • Pico SDK pinned to v2.2.0-UltraSupport-rel2 — includes the upstream CYW43 SPI driver, PIO0 force for RP2040, and clock GPIO function fix. (79df606@erichelgeson)
  • PlatformIO/Arduino remnants removed — leftover board JSON files, build scripts, and library manifests cleaned up. (e291c2e@erichelgeson)
  • Handle new bootloader_size in linker scripts — needed for the reshaped bootloader with shared log region. (39aee65@erichelgeson)
  • PR memory-usage comment — CI posts a memory diff against the latest GitHub release on each PR. (db5dbe9@erichelgeson)

Contributors

@androda · @degrunert · @erichelgeson · @morio (J. Morio Sakaguchi) · @PetteriAimonen · @reinauer (Stefan Reinauer)


Commits

CD-ROM, CD audio, image handling

  • 8b060639 cdrom: fix SPDIF crash from heap exhaustion on multi-BIN CUE sheets (issue #353) — Eric Helgeson
  • a2835e6e cdrom: fix SPDIF READ SUB-CHANNEL / seek wrong LBA (issue #353) — Eric Helgeson
  • b2f2fda6 fix: SPDIF PLAY AUDIO uses wrong offset for tracks with PREGAP — Eric Helgeson
  • 8f7e389a Fix CD-ROM and disk command correctness — Eric Helgeson (co-authored Stefan Reinauer)
  • 0d9ded17 Reduce seek overhead in CD sector reads — Eric Helgeson (co-authored Stefan Reinauer)
  • 389ce314 cdrom: Fix getTrackFromLBA() when track_end_lba is not given — Petteri Aimonen
  • b250f357 fix: add missing cdrom_track_end_lba resets in CUE sheet paths — Eric Helgeson
  • b2ea0739 Fix audio playback after CD change and stale trackinfo cache — John Morio Sakaguchi
  • 87cbe5b1 Fix audio playback with multiple CD-ROM drives — J. Morio Sakaguchi
  • 5611fc4a Fix audio array sizing and ID masks for wide SCSI support — J. Morio Sakaguchi
  • 30ed0641 Fix eject wrapping back to the first image for multi-bin/cue — John Morio Sakaguchi
  • e44445d1 Reset image_directory and bin_container on SD card close — John Morio Sakaguchi
  • f3019883 Skip geometry warning for images larger than 8 GB — Eric Helgeson

Tape

  • 79432e34 fix: tape SPACE command uses absolute position and unsigned count — Eric Helgeson
  • e4d81d49 fix: tape variable-block READ underlength/overlength conditions swapped — Eric Helgeson
  • 7bdd5a86 fix: tape READ BLOCK LIMITS and SPACE CDB byte extraction bugs — Eric Helgeson
  • b6ed6b14 tape: accept transfer length 0 as no-op in variable-block READ/WRITE — Eric Helgeson

Disk / SCSI core commands

  • c4f8a730 Add 12/16-byte disk commands and VERIFY/WRITE AND VERIFY support — Stefan Reinauer
  • 8bcc3c86 logging: Add missing 12- and 16-byte command names — Petteri Aimonen
  • 826b981a fix: add safe accessors for packed scsiId field, fix prefetch comparison bug — Eric Helgeson
  • beaada14 Fix scsiLogDataOut logging with NULL buffer — J. Morio Sakaguchi
  • 49b319fc Fix stack overflow during image selection back to IMG0 — Dennis Grunert
  • 1e1a1a51 MODE SENSE: Add Notch and Partition page (0Ch) — Eric Helgeson
  • 318a1c14 MODE SENSE: Add Verify Error Recovery page (07h) — Eric Helgeson
  • f914e04c MODE SENSE: Reject non-zero reserved CDB byte 3 — Eric Helgeson
  • f7feb1db scsi: only set Valid bit in REQUEST SENSE when Information field is meaningful — Eric Helgeson
  • b9bd4af5 scsi: WRITE to read-only media returns DATA_PROTECT sense key — Eric Helgeson

Initiator mode

  • e7ebcab0 Add Fixed VHD image output to initiator mode — Eric Helgeson
  • 20073247 Ultra: Fix issue with initiator mode on some drives — androda
  • 290f513c fix: USB MSC initiator mode no longer overrides hardware switch when SD absent — Eric Helgeson

DaynaPORT / WiFi / network

  • 7c205792 fix: gate DaynaPORT multi-packet READ(6) on CDB byte 5 bit 6 — Eric Helgeson
  • 9f795a73 Ignore global INI SCSI strings for network devices — John Morio Sakaguchi
  • 4af22d79 fix: Restore WiFi (DaynaPORT) for CMake build on all Pico W variants — Eric Helgeson
  • b0e1a4e5 fix: Ultra/Ultra_Wide RM2 WiFi with custom board headers and GCC 14 — Eric Helgeson
  • 79df6065 build: Update pico-sdk-internal to v2.2.0-UltraSupport-rel2 — Eric Helgeson

Toolbox

  • 24bbc205 toolbox: add SET_UPLOAD_DIR subcommand for firmware updates — Eric Helgeson
  • 25fdaa66 toolbox: rename SET_UPLOAD_DIR to SET_WORKING_DIR, add GET_WORKING_DIR — Eric Helgeson
  • 581c6c7f fix: toolbox creates shared dir before file operations — Eric Helgeson

Timing / sync / performance

  • 4df54b56 Align RP2 sync negotiation with target timing — Stefan Reinauer
  • 830acb41 Harden RP2 custom timing overrides — Eric Helgeson
  • 18283f09 scsi: lower DMA read-pacer floors for faster sync negotiation — Eric Helgeson
  • b2a0584c Fix delay_ns() to be cycle-accurate for sub-microsecond values — Eric Helgeson
  • 74c61a04 fix: correct TurboMax clk_hz from 252MHz to 250MHz — Eric Helgeson
  • f534dbf1 fix: only suggest overclocking when sync speed hits 10 — Eric Helgeson
  • cb4da9e8 build: switch application code from -Os to -O2 — Eric Helgeson
  • 1b9bcc4c Defer Vdd voltage drop warnings to reduce log noise — Eric Helgeson

Bootloader / boot / logging

  • cb61c370 feat: universal zip firmware update, shared bootloader log, and lastlog.txt — Eric Helgeson
  • 455510af Fix RP2350 bootloader XIP cache guard using wrong define name — Eric Helgeson
  • ecb2ee5a fix: bootloader log replay printing garbage after content — Eric Helgeson
  • 7655af0d fix: add background USB timer for reliable CDC enumeration on RP2040 — Eric Helgeson
  • 30ba8b11 fix: unset SOURCE_DATE_EPOCH so DATE/TIME show real build time — Eric Helgeson
  • 39aee652 Handle new bootloader_size in ld scripts — Eric Helgeson
  • ad1494a0 log: decode SD card OID as ASCII and add manufacturer name — Eric Helgeson

Safety / diagnostics

  • 20823c98 Add hardware stack overflow protection and enhanced crash diagnostics for RP2350 — Eric Helgeson
  • 887508b6 fix: stack overflow crash on RP2350 during image init — Eric Helgeson
  • 1851c056 fix: reduce RP2350 stack to 3KB for Audio SPDIF compatibility — Eric Helgeson
  • 15b7d107 Add core1 mutex to protect flash writes during ROM drive loading — Petteri Aimonen
  • 81738d22 fix: eliminate 31.8 KB C++ exception bloat and improve RP2040 symbol placement — Eric Helgeson
  • 2aa6130b build: add static stack usage analysis to build pipeline — Eric Helgeson

Build system / CI / docs

  • 315b2080 build: Allow for better release/pre-release management with tags — Eric Helgeson
  • 4a3a15e6 build: add include guard to minGlue.h for testability — Eric Helgeson
  • 1c41f993 build: migrate from PlatformIO to CMake with Nix flake — Eric Helgeson
  • 8d1794bb build: Add macOS support and fix build gotchas — Eric Helgeson
  • e291c2eb fix: Remove last of PlatformIO & Arduino — Eric Helgeson
  • ae0041d5 build: Fix build after rebase on cmake — Eric Helgeson
  • db5dbe93 ci: add PR memory usage comment — Eric Helgeson
  • f62c6946 ci: enable cachix push with auth token — Eric Helgeson
  • 0aa11900 ci: bump sticky-pull-request-comment to v3 — Eric Helgeson
  • 329e2334 build: upgrade GitHub Actions to Node.js 24 compatible versions — Eric Helgeson
  • 69b61321 build: prevent duplicate CI runs on PR branches — Eric Helgeson
  • 591224c2 build: update analyze_crashlogs workflow to ubuntu-latest and checkout v4 — Eric Helgeson
  • b69d1185 build: add --clobber to tag release upload fallback — Eric Helgeson
  • f4d3a728 build: nix flake update — Eric Helgeson
  • 9e972ed7 docs: add CMakePresets.json for IDE integration — Eric Helgeson
  • 9b508c0a docs: Update to reference Ultra/Ultra Wide — Eric Helgeson
  • f71cd891 docs: Add manual cmake setup in addition to nix — Eric Helgeson
  • 5017ee45 docs: Add back missing images — Eric Helgeson
  • 3079692a dev — Eric Helgeson