Skip to content

Two IEC bugs break channel-based serial I/O (CHKIN+CHRIN path) #116

@cr

Description

@cr

Two bugs in the STD (C64-compatible) build prevent channel-based serial reads (OPEN+CHKIN+CHRIN) from working on IEC devices. LOAD is unaffected. It uses its own serial protocol that bypasses both code paths.

Bug 1: TKSA corrupts secondary address

src/kernal/iec/tksa.s applies ora #$90 to the incoming accumulator:

; tksa.s line 31 (CONFIG_IEC path)
ora #$90
jmp common_untlk_tksa

Callers (e.g. chkin_iec.s) pass SA | $60 as required by the IEC protocol and documented in the comment on line 26-27 of the same file: "it is the caller responsibility to provide value ORed with $60." The spurious ora #$90 turns SA | $60 into SA | $F0, which is an OPEN command ($F0), not a talk-secondary-address ($60).

The UNTLK path that shares common_untlk_tksa is unaffected. It enters with lda #$5F at untlk.s:43, before the shared label.

Fix: Remove the ora #$90 from tksa.s.

Bug 2: open_iec skips bus communication for empty filenames

src/kernal/iec/open_iec.s short-circuits when FNLEN == 0:

open_iec:
    ldy FNLEN
    beq open_iec_done      ; ← skips LISTEN + SECOND + UNLISTEN entirely

This skips all IEC bus communication, and LISTEN, SECOND(SA|$F0), and UNLISTEN are never sent. The file is recorded in the internal FAT/LAT/SAT tables, but the drive is never told to open the channel.

This breaks any OPEN lfn,dev,sa,"" with an empty filename. The most common case is reading the drive error channel: OPEN 15,8,15,"" (or OPEN 15,8,15). The stock KERNAL sends LISTEN + SECOND + UNLISTEN even with an empty command string. The drive needs the bus transaction to know channel 15 was opened.

Fix: Remove the beq open_iec_done branch (or move it after the LISTEN+SECOND+UNLISTEN sequence, before iec_send_file_name). The iec_send_file_name routine already handles FNLEN=0 correctly. It sends zero bytes then calls UNLSN.

Impact

Together, these two bugs break every program that uses the standard CBM channel I/O pattern:

SETNAM / SETLFS / OPEN / CHKIN / CHRIN loop / CLOSE

This includes directory listing, error channel reads, and any sequential file reads that use CHRIN instead of LOAD.

Bug 1 alone breaks channel reads even when the filename is non-empty (e.g. OPEN 1,8,0,"$").
Bug 2 alone breaks channel opens with empty filenames (e.g. OPEN 15,8,15).

Test case

Reads the drive error channel and should print 00, OK,00,00 (or similar):

10 OPEN 15,8,15
20 INPUT#15,A$,B$,C$,D$
30 PRINT A$;",";B$;",";C$;",";D$
40 CLOSE 15

Channel-based directory read and should print the first byte of the directory file:

10 OPEN 1,8,0,"$"
20 GET#1,A$
30 PRINT ASC(A$)
40 CLOSE 1

On stock KERNAL both work. On open-roms STD, the first hangs or returns empty (both bugs), the second hangs (bug 1 alone).

Validation

Both bugs were confirmed by binary-patching the built kernal_generic.rom:

  • Offset $1388: replaced 09 90 (ora #$90) with EA EA (NOP NOP)
  • Offset $1BAF: replaced F0 15 (beq +21) with EA EA (NOP NOP)

With both patches applied, channel-based error channel reads work correctly in VICE x64sc 3.10 with true drive emulation. Named directory listing still hangs due to issue #117.

Tested with: open-roms STD build (C64-compatible), VICE x64sc 3.10, 1541 D64 disk image.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions