Skip to content

Serial / Modem

GSSquared includes a virtual Hayes-compatible modem you can attach to a serial port. From Apple II terminal software it behaves like a phone-line modem — except outbound “numbers” are TCP hosts, and inbound telnet on port 6502 rings the guest.

What you need

  1. A serial port: IIgs built-in SCC, or a Super Serial Card in a slot.
  2. That port’s attachment set to Modem — see Serial & Parallel Connections.
  3. A native build. The browser build does not include the modem (no SDL_net).

How to dial

Use any normal serial program (ProTERM, Spectrum, TelCom, etc.). Example:

ATDTcqbbs.ddns.net:6800

That connects to host cqbbs.ddns.net, TCP port 6800.

Result codes default to words (OK, CONNECT 9600, RING, NO CARRIER, ERROR). ATV0 switches to Hayes numeric codes; ATV1 restores words. AT&F also restores V1.

Numeric (V0): 0 OK, 1 CONNECT (300 / unknown), 2 RING, 3 NO CARRIER, 4 ERROR, 5/10/11/12/14/28/18 CONNECT at 1200 / 2400 / 4800 / 9600 / 19200 / 38400 / 57600 (Hayes Smartmodem + GBBS; 28 and 18 are Accura / Warp Six).

How to answer

With Modem attached, GSSquared listens on TCP port 6502 (on all host interfaces). When a telnet client connects (for example telnet <your-host> 6502), the guest sees Hayes RING — immediately, then about every 3 seconds — and carrier stays down.

Answer from the terminal program:

ATA

(ATA0 is the same.) The modem raises CD, sends CONNECT <baud>, and the telnet session is fully connected. If nothing is ringing, ATA returns NO CARRIER.

ATH (or ATZ / AT&F) while ringing drops the inbound caller and returns OK. If the caller hangs up before you answer, RING stops and there is no NO CARRIER (the modem never went off-hook).

ATS0=n auto-answers after n RING results (ATS0=1 on the first ring). ATS0=0 (default, also after AT&F) turns auto-answer off so the guest must send ATA. ATS0? reports the current value.

What the caller sees

Plain telnet <your-host> 6502 is enough — no set binary, no mode character, no client-side stty games. On answer, GSSquared negotiates as a telnet server: it offers WILL ECHO, WILL SUPPRESS-GO-AHEAD, and binary in both directions, which puts a standard client in character-at-a-time mode with local echo off. Every keystroke reaches the BBS as you type it, and the BBS does the echoing.

A caller that refuses binary mode gets NVT line ends (carriage return/newline) bridged for it: the guest's bare CR goes out as CR LF so the screen scrolls, and the caller's CR LF or CR NUL for Return arrives as a single CR. So even a client that refuses every option gets a readable session.

Once binary mode is agreed — which any normal telnet client accepts — that translation is off and the session is 8-bit transparent in both directions, so ZMODEM and XMODEM transfers work. GBBS sends its own linefeeds anyway, so nothing is lost either way.

Only one ModemDevice can bind 6502. A second serial port also set to Modem stays outbound-only (the console logs the listen failure). Extra inbound connections while already ringing or online are refused.

How to hang up

Send the Hayes escape sequence, then hang up:

+++
ATH

(Wait about a second of silence before and after +++.)

+++ returns to command mode but keeps carrier detect asserted (the TCP session is still up). ATO (or ATO0) goes back to data mode and sends CONNECT again. ATH, a failed dial, or a dropped socket deasserts CD so guest software that watches 6551 ST_DCD or SCC RR0 DCD sees hang-up. DSR stays asserted whenever the virtual modem is attached (powered). See SerialPortSpec.md.

File capture, clipboard, or a real serial port

Set the port attachment to File to save serial output to a host file (a toast shows the filename when the file closes, which happens automatically after 10 seconds of no data). Clipboard copies the captured/printed text to the host clipboard on close. Serial attaches a real host serial port. Details: Serial & Parallel Connections.