COLOR 64 BBS AT 9600 BAUD

Updated October 19, 2026: a new section at the end, what's happened since, covers the review, the slow-caller fix and where the mod stands now.
If you called bulletin boards on a Commodore 64, there's a good chance you called a Color 64 board. Greg Pfountz's BBS program, first released in 1985, gave the 64 a colourful board with message bases, file transfers, mail, voting, online games and more. Sysops kept it running for years, and plenty of us modded it until it barely looked like the original.
It has always had one limit: 2400 baud. Color 64 talks to the modem through the 64's built-in RS-232 routines, and those top out at 2400. That was fine in 1987. It isn't fine when a caller's modem can go a lot faster.
The UP9600 hack
UP9600 is Daniel Dallmann's interface for the 64's user port. It's a small change to the user port's wiring that lets the 64's own CIA chips send and receive the serial data in hardware, instead of the processor timing every bit. With it, a stock 64 can talk at 9600 baud. Terminal programs have used it for years. Color 64 never did.
So we added it.
Color 64 7.40
Color 64 7.40 is our name for the UP9600 edition of Color 64 7.37. Here's what's in it:
- 9600 baud. A new driver for the UP9600 interface sits inside the BBS's machine language, and the BBS's BASIC programs use it for everything: the menus, the message bases, mail, the games, uploads and downloads.
- Falls back to 2400. If the BBS doesn't find a UP9600 interface at boot, it uses the original 2400 baud routines, just as it always did.
- Knows when a caller hangs up. The BBS watches for the modem's CONNECT and NO CARRIER messages, so it works with modern WiFi modems as well as old Hayes modems.
- SuperCPU friendly. Sysops running a SuperCPU know the old trick: slow it down for file transfers, then speed it back up. 7.40 does that for you, around every Xmodem and Punter transfer.
- CMD drives. It runs from a CMD HD and a RAMLink, the way the big boards ran back in the day.
- "V7.40" everywhere. The boot screen, the sysop's screens and the program names all say 7.40.
How it works
For the technically minded, here's what's under the hood.
Why the 64 stops at 2400. The KERNAL's RS-232 routines are "bit-banged": a CIA timer fires an interrupt for every single bit, and the processor shifts each bit in or out by hand. At 2400 baud that's an interrupt about every 400 cycles of the 64's 1 MHz processor. At 9600 it would be one every 100 cycles, and the 64 simply can't keep up while it also runs a BBS.
What UP9600 does instead. Each of the 64's two CIA chips has a serial shift register built in, and UP9600 wires the user port so the CIAs do the bit work:
- Sending goes out through CIA 1's shift register, clocked by CIA 1's timer A. The processor hands it a byte and moves on.
- Receiving comes in through CIA 2's shift register. The start bit of each byte raises an interrupt on CIA 2's FLAG line, which starts CIA 2's timer B. Timer B's output clocks the shift register, so the eight data bits are sampled in hardware.
The processor deals with one interrupt per byte instead of one per bit. That's what makes 9600 possible.
The driver. We wrote a new UP9600 driver for Color 64 in 6502 assembly. It fits in the 640 bytes at $CD80-$CFFF, right after the BBS's own machine language, with its variables at $02A7. The page that used to hold the boot banner now holds the code that runs once at boot: it looks for the interface, installs the driver, and falls back to the KERNAL's routines if there's no UP9600 there. A few details took some care:
- No interrupts during disk access. The 64's serial bus to the disk drives is timing-critical, and an interrupt in the middle of a byte can corrupt it. The driver only runs its send timer while characters are actually going out, and the KERNAL already waits for the modem to finish sending before it talks to a drive, so no interrupt ever lands in the middle of a disk operation.
- Keeping the clock. The 60 Hz interrupt that drives the 64's clock normally runs on CIA 1's timer A, which is now the send clock. The driver moves it to the VIC chip's raster interrupt, once per frame, with a correction tick so it keeps time. (The first version used CIA 1's timer B, and the clock stood still during disk access; see the second look.)
- The BBS doesn't know the difference. The driver keeps the KERNAL's buffer pointers and RS-232 status byte, so Color 64's machine language and its Xmodem and Punter overlays work unchanged, apart from a handful of byte patches: the place where the BBS starts sending now calls the driver, and the carrier checks read the driver's carrier byte.
Carrier. Color 64 watches the modem's carrier detect line to know when a caller hangs up. 7.40 takes carrier from the modem's CONNECT and NO CARRIER messages instead, so it works with WiFi modems whether or not their carrier line is wired. A sysop with a modem that drives the line properly can switch back with one POKE.
The BASIC changes. Every overlay's carrier check now reads the driver's carrier byte. The routine that works out the KERNAL's bit timing from the baud rate returns early above 2400, since the old arithmetic broke at 9600 (CONNECT 9600 crashed it with ?ILLEGAL QUANTITY). The BBS accepts CONNECT 9600 as well as 1200 and 2400, and it starts the driver right after it opens the modem channel and stops it before closing it.
SuperCPU. The CIA timers run at 1 MHz whatever speed the processor runs at, so the baud rate stays right at 20 MHz. The file transfer overlay drops the SuperCPU to 1 MHz (POKE 53370,0) for Xmodem and Punter and turns turbo back on afterwards (POKE 53371,0). On a 64 without a SuperCPU those addresses do nothing.
Testing. The driver has its own test suite: all 256 byte values, long blasts and back-to-back bursts, full duplex, and the clock staying correct while sending and after disk access. It passes on a plain 64, and on a SuperCPU at 20 MHz in both PAL and NTSC. In VICE, the BBS sends around 440 to 540 characters a second at 9600.
Where it is
Our board has been running Color 64 7.40 since October 17, on a SuperCPU with a CMD HD and a RAMLink, all emulated in VICE, answering callers from the internet through a small modem bridge. We've called it from real Commodore 64s with WiFi modems at 9600, and now at 4800 and 2400 as well: logged in, read messages, played the games, uploaded files, logged off, called again. It appears to be stable. The board has stayed up through every call and every hang-up, and it still keeps correct time.
What the board itself has been up to, the new login screen, the games room and the seasonal welcome screens, is in What's new on the Comm-Adore BBS.
What's happened since
The second look. Before anyone else runs this, we went back over the driver and the BASIC patches line by line and then let the tests run all night. That turned up a dead 2400 fallback, a clock that stood still during disk access, an interrupt storm in full duplex and a handful of smaller things, all fixed. The whole list, with why each one mattered, is in Color 64 at 9600, the second look.
Slow callers crashed their modems. Callers at 9600 were fine. A caller at 2400 or 4800 got the login picture half drawn, then a screen full of hex, and then their WiFi modem rebooted. The board never noticed; it just saw the caller drop. The same modem has called other boards at 2400 for years without trouble, so at first it looked like something in 7.40.
It wasn't Color 64, and it wasn't the driver. It took a bench rig to find: a WiFi modem on a USB cable calling the board at 2400 with its free memory printed once a second, until the crash dump landed on a PC instead of a C64 screen. The dump pointed at the modem's WiFi stack failing to get memory. The reason was the bridge that stands between the emulated 64 and the internet. VICE hands it the BBS's output one character at a time, about one a millisecond, and the bridge sent each one straight out as its own packet. At 9600 the modem drains them as fast as they arrive. At 2400 it can't. A thousand-character picture became a thousand little packets queued inside an ESP8266 that has about 40 KB of memory to its name, and when the WiFi stack needed some for the next beacon from the access point, there was none left.
The bridge now gathers the BBS's output for a few hundredths of a second and sends it in pieces of up to a kilobyte. Same bytes, a small fraction of the packets. A modem that used to crash with 12 KB free never dips below 38 KB now, and callers at 2400 and 4800 get every picture. The first version of that fix cut the logoff picture short, because the last piece was still waiting in the bridge when the board dropped DTR; the bridge now sends everything it holds before it hangs up.
Our own modem got tougher too. While we were in there, our WiFi modem firmware got a forwarding loop that never blocks on the serial port, so it keeps up with its WiFi side at low baud rates, and a crash log that is saved to flash, survives the reboot and reads out with an AT command. The next fault, if there is one, won't need a bench rig.
What's left
A real UP9600 cable on real silicon. VICE hands received bytes straight to the shift register and doesn't model the clock pulses on the user port, so the receive timing is proven on paper and in the emulator, not yet in a chip. Then Xmodem and Punter at 9600 end to end, the PAL clock trim, and the release package: the patched programs, the driver and the install steps, for any sysop running Color 64 7.37. If you still run a Color 64 board, or you've been meaning to bring one back, keep an eye on this blog.
Color 64 is copyright Greg Pfountz. UP9600 is Daniel Dallmann's design. The 7.40 mod is from Comm-Adore, comm-adore.com.