Altair 8800 notes

In February 2017, I visited Living Computers: Museum + Labs (LCM+L) and had a great time trying the various machines available. One of the systems in the vintage computers collection is the MITS Altair 8800, which is connected to a teletype. During my visit, I typed in two short BASIC programs, and was delighted to find that they ran well and made a tremendous noise on the teletype.

This is my attempt to better understand the Altair so that I can be prepared for my next visit.

Table of contents:

Altair simulators

A few simulators are available for the Altair. Here are the best two I’ve used:

Also available:

Which simulator you choose will depend on your need. If you like to visually see and maniuplate the Altair front panel, perhaps altairsim is the best choice. If you need a “headless” system, perhaps altairz80 will suit better. (For reasons explained later, I think altairz80 is a better choice than SIMH altair.)

Also worth mentioning is the availability of the Altair 8080 Clone computer, by Mike Douglas. This remarkable device is a “fully functional replica” of the Altair 8800, using modern hardware on the inside. Mr Douglas has also provided a wealth of information, software, and excellent videos demonstrating the features of the Altair, which he makes available free of charge on his website.

altairsim

This is my favourite Altair emulator, because I like watching the graphical front panel whilst computerizing. It should run on any system which has some UNIX and X support. altairsim comes with Makefiles for BSD, Cygwin (Windows), Linux, OS X, and Solaris.

Compiling altairsim

First download and compile altairsim for your particular platform. Here is an example from OS X 10.11 (“El Capitan”).

Download and extract the software, then build the frontpanel component:

% curl -sO http://www.autometer.de/unix4fun/z80pack/ftp/z80pack-1.36.tgz
% tar zxf z80pack-1.36.tgz
% cd z80pack-1.36/frontpanel
% make -f Makefile.osx
[...]
g++ ‑shared ‑L/usr/X11/lib ‑L/usr/local/lib ‑ljpeg ‑lGL ‑lGLU ‑lX11 jpeg.o lpanel.o lp_gfx.o lp_main.o lp_utils.o lp_window.o lp_switch.o lp_font.o lp_materials.o ‑o libfrontpanel.dylib

Be sure to copy libfrontpanel.dylib to a shared library path!

Next, link the libfrontpanel.dylib file to the destination directory of the altairsim binary, and build the altairsim binary itself:

% cd ../altairsim
% ln -s ../frontpanel/libfrontpanel.dylib
% cd srcsim
% make -f Makefile.osx 
[...]
gcc sim0.o sim1.o sim1a.o sim2.o sim3.o sim4.o sim5.o sim6.o sim7.o simctl.o simint.o memory.o iosim.o simfun.o simglb.o unix_terminal.o unix_network.o config.o altair‑88‑sio.o altair‑88‑2sio.o tarbell_fdc.o cromemco‑dazzler.o proctec‑vdm.o ‑L../../frontpanel ‑L/usr/local/lib ‑L/opt/X11/lib ‑lfrontpanel ‑ljpeg ‑lGL ‑lGLU ‑lX11 ‑o ../altairsim

Done.

The final preparatory step is to disable the Tarbell bootstrap ROM (via the tarbell_rom_enabled setting in conf/system.conf), as it will interfere with the normal boot-up sequence. (It’s possible to leave it enabled using a slightly more complicated start-up sequence – see the later subsection.)

% cd ../conf
% mv system.conf system.conf.bak
% sed 's,^tarbell_rom_enabled,#tarbell_rom_enabled,' system.conf.bak > system.conf
% cd ..
% 

Loading 4K/8K BASIC 1.0/3.2/4.0/’78

Now altairsim is ready to use! Let’s load 4K BASIC, version 3.2:

% ./altairsim -x basic4k32.hex

 #####    ###     #####    ###            #####    ###   #     #
#     #  #   #   #     #  #   #          #     #    #    ##   ##
#     # #     #  #     # #     #         #          #    # # # #
 #####  #     #   #####  #     #  #####   #####     #    #  #  #
#     # #     #  #     # #     #               #    #    #     #
#     #  #   #   #     #  #   #          #     #    #    #     #
 #####    ###     #####    ###            #####    ###   #     #

Release 1.36, Copyright (C) 1987-2017 by Udo Munk
Altair 8800 Simulation Release 1.17, Copyright (C) 2008-2017 by Udo Munk

CPU speed is 2 MHz
RAM size  252 pages, 0000H - fbffH
ROM size    4 pages, fc00H - ffffH
Boot switch address at fe00H

Loader statistics for file basic4k32.hex:
START : 0000H
END   : 0fffH
LOADED: 1000H (4096)

FrontPanel Simulator v2.1 Copyright (C) 2007-2015 by John Kichury

At this point, the front panel should hopefully open on the screen:

Altair 8080 Front Panel

To start BASIC, click the ON switch to turn the Altair on; the terminal screen will clear, and the blinkenlights will illuminate (but not blinken just yet). Next, click RUN; this will begin execution at address 0. If all went well, BASIC will start, and you will see the following at the terminal:


MEMORY SIZE? [Enter]
TERMINAL WIDTH? [Enter]
WANT SIN? Y

61143 BYTES FREE

BASIC VERSION 3.2
[4K VERSION]

OK

The obligatory(?) “Hello, World!”-type program:

10 PRINT "HELLO, WORLD!"
RUN
HELLO, WORLD!

OK

When you’re through with BASIC (or BASIC is through with you), just click the OFF switch to terminate altairsim. It will give you a parting shot:

System powered off, bye.

And that’s it! The same procedure works for 4K BASIC, version 4.0 (basic4k40.hex), and 8K BASIC versions 3.2, 4.0, and ’78 (basic8k32.hex, basic8k40.hex, and basic8k78.hex, respectively).

4K 3.24K 4.08K 3.28K 4.08K ’78

MEMORY SIZE? 
TERMINAL WIDTH? 
WANT SIN? Y

61143 BYTES FREE

BASIC VERSION 3.2
[4K VERSION]

OK

MEMORY SIZE? 
TERMINAL WIDTH? 
SIN? Y
61132 BYTES FREE
4K BASIC 4.0
COPYRIGHT MITS 1976
OK

MEMORY SIZE? 
TERMINAL WIDTH? 
WANT SIN-COS-TAN-ATN? Y

58440 BYTES FREE

ALTAIR BASIC VERSION 3.2
[EIGHT-K VERSION]

OK

MEMORY SIZE? 
TERMINAL WIDTH? 
WANT SIN-COS-TAN-ATN? Y

57988 BYTES FREE
ALTAIR BASIC REV. 4.0
[EIGHT-K VERSION]
COPYRIGHT 1976 BY MITS INC.
OK


11704 BYTES FREE

BASIC, Version of 02/03/78
START

OK
* 

There is a slight wrinkle when loading version 1.0, however: BASIC 1.0 expects an SIO rev 0 board. There are two strategies for dealing with this, both relatively straightforward.

Loading 8080 BASIC 1.0 using the SIO Rev 0 board

The easiest solution if using altairsim is to emulate a rev 0 board instead of the default rev 1 board. To do that, change the sio0_revision option in conf/system.conf from a 1 to a 0:

% cd conf
% mv system.conf system.conf.bak
% sed 's,^\(sio0_revision[^0-9]*\)[0-9]$,\10,' system.conf.bak > system.conf
% cd ..

Now BASIC 1.0 should load:

% ./altairsim -x basic4k10.hex

 #####    ###     #####    ###            #####    ###   #     #
#     #  #   #   #     #  #   #          #     #    #    ##   ##
#     # #     #  #     # #     #         #          #    # # # #
 #####  #     #   #####  #     #  #####   #####     #    #  #  #
#     # #     #  #     # #     #               #    #    #     #
#     #  #   #   #     #  #   #          #     #    #    #     #
 #####    ###     #####    ###            #####    ###   #     #

Release 1.36, Copyright (C) 1987-2017 by Udo Munk
Altair 8800 Simulation Release 1.17, Copyright (C) 2008-2017 by Udo Munk

CPU speed is 2 MHz
RAM size  252 pages, 0000H - fbffH
ROM size    4 pages, fc00H - ffffH
Boot switch address at fe00H

Loader statistics for file basic4k10.hex:
START : 0000H
END   : 11deH
LOADED: 11dfH (4575)

FrontPanel Simulator v2.1 Copyright (C) 2007-2015 by John Kichury


MEMSIZ? [Enter]
WANT SIN-COS-ATN? Y
1521 BYTES FREE

8080 BASIC VER 1.0

READY

Loading 8080 BASIC 1.0 using the SIO Rev 1 board

The previous solution is simple, however it changes the configuration of altairsim for all programs. There is another option: patch BASIC to work ‘natively’ with a rev 1 SIO board. This has already been done by Mike Douglas (of Altair 8800 Clone fame); all that remains is to convert the punched tape file into an Intel HEX file which altairsim can load.

To convert binary files to Intel HEX, I’m using the intelhex Python library. Here’s how I did it:

First, download the BASIC 1.0 tape, and the intelhex package, then extract it. I don’t plan to keep the intermediate work, so I’m doing all this from a personal tmp directory.

% cd ~/tmp
% curl -s -o basic10.tap http://altairclone.com/downloads/basic/Paper%20Tape%20and%20Cassette/BASIC%20Ver%201-0.tap
% curl -sO https://pypi.python.org/packages/01/66/8fab869edcc0eaf8fc030472ff379b8eeee2ef3b42f8aec6bd84e9f735e3/intelhex-2.2.1.tar.gz
% tar zxf intelhex-2.2.1.tar.gz

The accompanying documentation for the patched BASIC 1.0 tape says: “…the tape is pretty much just a binary dump of BASIC from memory. The image is preceded by a string of NULLs for leader and a sync byte of 6Ah to mark the start of the memory image.“ So it’s necessary to trim some bytes from the first part of the tape, essentially everything up to and including the first 0x6a byte.

The first chunk of the tape looks like this:

% hexdump -C basic10.tap | head -3
00000000  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
00000010  00 00 00 00 00 00 00 00  00 00 00  c3 7e 10 00  |............~..|
00000020  00 00 00 00 e3 be 23 e3  c2 61 05 7f c5 7e 23 fe  |......#..a...~#.|

The 0x6a byte is clearly visible at position 0x1c, or 28 in decimal. So that is how many bytes need to be trimmed. Do that with dd and check the result – it should begin with 0xc3:

% dd if=basic10.tap of=basic10.bin bs=1 skip=28
4480+0 records in
4480+0 records out
4480 bytes transferred in 0.013439 secs (333360 bytes/sec)
% hexdump -C basic10.bin | head -3
00000000  c3 7e 10 00 00 00 00 00  e3 be 23 e3 c2 61 05 7f  |.~........#..a..|
00000010  c5 7e 23 fe 20 c3 18 05  e6 7f c3 d4 03 00 00 00  |.~#. ...........|
00000020  7c 92 d8 c0 7d 93 c9 00  00 00 00 00 00 00 00 00  ||...}...........|

Convert the resulting file into Intel HEX format:

% PYTHONPATH=intelhex-2.2.1 python intelhex-2.2.1/scripts/bin2hex.py basic10.bin basic10.hex
% head -3 basic10.hex
:10000000C37E100000000000E3BE23E3C261057F51
:10001000C57E23FE20C31805E67FC3D4030000007D
:100020007C92D8C07D93C900000000000000000051

Perfect! You can even see the first byte is 0xc3. Try it out with altairsim, leaving sio0_revision at 1 in conf/system.conf:

% cp basic10.hex ~/z80pack-1.36/altairsim
% cd ~/z80pack-1.36/altairsim
% grep ^sio0_revision conf/system.conf
sio0_revision              1
% ./altairsim -x basic10.hex

 #####    ###     #####    ###            #####    ###   #     #
#     #  #   #   #     #  #   #          #     #    #    ##   ##
#     # #     #  #     # #     #         #          #    # # # #
 #####  #     #   #####  #     #  #####   #####     #    #  #  #
#     # #     #  #     # #     #               #    #    #     #
#     #  #   #   #     #  #   #          #     #    #    #     #
 #####    ###     #####    ###            #####    ###   #     #

Release 1.36, Copyright (C) 1987-2017 by Udo Munk
Altair 8800 Simulation Release 1.17, Copyright (C) 2008-2017 by Udo Munk

CPU speed is 2 MHz
RAM size   48 pages, 0000H - 2fffH
Boot switch address at 0000H

Loader statistics for file basic10.hex:
START : 0000H
END   : 117fH
LOADED: 1180H (4480)

FrontPanel Simulator v2.1 Copyright (C) 2007-2015 by John Kichury


MEMSIZ? [Enter]
WANT SIN-COS-ATN? Y
1521 BYTES FREE

8080 BASIC VER 1.0

READY

Loading BASIC with the Tarbell bootstrap ROM enabled

There may be cases where you’d like to keep the Tarbell bootstrap ROM enabled; perhaps you are using disk-based systems with some regularity and don’t want to have to turn it off to load “diskless” BASIC. There is still a way to load BASIC with the Tarbell ROM enabled: you must start BASIC at an address other than 0.

If you examine the first few bytes of 4K BASIC, version 3.2, you’ll see the sequence: F3 C3 21 0D:

% head -1 basic4k32.hex
:200000009004F9077EE3BE23E3C2D001237EFE3AD0C35E04F53A2700C36E030058

The excellent Altair BASIC 3.2 (4K) - Annotated Disassembly site, in 1.1 Restarts, has the disassembly:

0000	F3	Start	DI	
0001	C3210D		JMP Init

This code disables interrupts, then does an unconditional jump to location 0x0d21 (little-endian), or 6441 octal. If you begin execution from there, you can skip over the clobbered code at address 0. To do that:

  1. Power the Altair on with the ON switch.
  2. Enter 6441 in the Address switches; an switch in the ‘up’ position is a 1. For 6441, flip the following five switches up: 11, 10, 8, 5, 0.
  3. Push the EXAMINE switch to point the Altair at that memory location. The data lights D5 and D0 should illuminate (as will the address lights corresponding to the switches you selected).
  4. Reset the address switches back to 0. (Not always 100% necessary, but some versions of BASIC use the sense switches 8 and higher to detect configuration such as I/O port numbers.
  5. Push the RUN switch.

And BASIC should start at this point with the usual MEMORY SIZE? question:

MEMORY SIZE? [Enter]
TERMINAL WIDTH? [Enter]
WANT SIN? Y



BASIC VERSION 3.2
[4K VERSION]

OK

Notice that there is less memory free due to the presence of the ROM (61143 bytes free without, 8919 bytes free with).

Actually there are many possible entry points which will (eventually) fire up the init code, since the Altair ignores invalid opcodes, and many BASIC error handler routines will funnel you there. You may see gibberish characters or syntax errors using a non-standard entry point, though.

Entry points for various BASIC versions

Here are standard entry points gleaned from the various HEX files:

BASIC versionInit address (octal)
BASIC 1.010176
4K BASIC 3.26441
4K BASIC 4.06746
8K BASIC 3.213604
8K BASIC 4.015013
8K BASIC ’78400 or 20633

If you’re having trouble loading BASIC this way, make sure that you’re pressing EXAMINE after loading the address switches, and resetting the address switches back to zero before pressing RUN.

altairz80

If you’re looking for a headless (text-only) emulator, I recommend altairz80. It has the added bonus of the familiar SIMH interface, so if you’re used to other SIMH-based emulators, you’ll feel right at home with this one.

Installing SIMH

As I already had SIMH installed for other platforms, I won’t go over the installation process here in any great detail. On OS X / macOS, it’s as simple as installing Homebrew, then running:

% brew install simh

Downloading Altair software

Once installed, you’ll need some software to run. Unlike altairsim, which reads Intel HEX files, altairz80 reads raw binary images. Here are two places to get software:

Of course, you can use software from anywhere, including the Z80pack, though you may need to do some file format conversion.

Loading 4K BASIC 3.2 and 4K/8K BASIC 4.0

Here’s an example session of downloading the software pack, and launching 4K BASIC, version 3.2:

% curl -sO https://schorn.ch/cpm/zip/altsw.zip
% unzip -qd altsw altsw.zip
% cd altsw 
% altairz80 bas432

Altair 8800 (Z80) simulator V3.9-0
4096 bytes [16 pages] loaded at 0.

MEMORY SIZE? [Enter]
TERMINAL WIDTH? [Enter]
WANT SIN? Y

61911 BYTES FREE

BASIC VERSION 3.2
[4K VERSION]

OK
[Control-E]
Simulation stopped, PC: 00386 (JZ 0382h)
sim> exit
Goodbye
% 

The file bas432 contains all of the necessary SIMH commands to load and start 4K BASIC 3.2:

% grep -v ^\; bas432
set cpu 8080
set cpu noitrap
set sio ansi
set sio upper
set cpu altairrom
l 4kbas32.bin 0
d sr 8
g 0

SIMH users will be familiar with the syntax here. The script sets a few CPU and SIO options, loads the image starting at address 0, deposits 8 at the switch register (that is, sets the sense switch 11 on the front panel), and begins execution at address 0. The switch register setting selects the I/O board type for the console, in this case a 2SIO board.

The bas440 script loads 4K BASIC 4.0 and bas8 loads 8K BASIC 4.0. Technically the d sr 8 command isn’t necessary with 4K or 8K BASIC 4.0, as they default to the 2SIO board. However, raising sense switch 11 has no ill effect.

The documentation for altairz80 is quite good, and covers the above procedure and many others.

Loading 8K BASIC 3.2

To run 8K BASIC 3.2, convert from the Intel HEX file shipped with altairsim. For example:

% cd ~/tmp
% PYTHONPATH=intelhex-2.2.1 python intelhex-2.2.1/scripts/hex2bin.py ~/z80pack-1.36/altairsim/basic8k32.hex ~/altsw/8kbas32.bin
% cd ~/altsw
% sed 's,8kbas\.bin,8kbas32.bin,' bas8 > bas832
% altairz80 bas832

Altair 8800 (Z80) simulator V3.9-0
8192 bytes [32 pages] loaded at 0.

MEMORY SIZE? [Enter]
TERMINAL WIDTH? [Enter]
WANT SIN-COS-TAN-ATN? Y

59208 BYTES FREE

ALTAIR BASIC VERSION 3.2
[EIGHT-K VERSION]

OK
[Control-E]
Simulation stopped, PC: 004DF (JZ 04DBh)
sim> exit
Goodbye
% 

Loading 8080 BASIC 1.0

To run BASIC 1.0, you must change the SIO port to the one used by the SIO Rev 1 board:

% cat << EOF > bas10
heredoc> reset cpu
heredoc> set cpu 8080
heredoc> set cpu noitrap
heredoc> set cpu altairrom
heredoc> set sio ansi
heredoc> set sio upper
heredoc> set sio port=00/0/00/01/00/f/00/f
heredoc> set sio port=01/0/00/00/00/f/00/t
heredoc> l bas10.bin 0
heredoc> g 0
heredoc> EOF
% altairz80 bas10

Altair 8800 (Z80) simulator V3.9-0
4480 bytes [18 pages] loaded at 0.

MEMSIZ? [Enter]
WANT SIN-COS-ATN? Y
1521 BYTES FREE

8080 BASIC VER 1.0

READY
[Control-E]
Simulation stopped, PC: 003F1 (IN 00h)
sim> exit
Goodbye
% 

That set sio port bit was a bit of a head-scratcher. Initially I was just guessing at values until I got the MEMSIZ? prompt. Eventually I found an explanation that made sense to me in the 88-SIO manual, p. 2 (PDF p. 3). The table provided is this:

Data bitLogic low levelLogic high level
7Output device Ready (a ready pulse has been sent from the device).
Also causes a hardware interrupt to occur if interrupt enabled.
Not Ready
6(not used)(not used)
5Data Available (a word of data is in the buffer on the I/O board)
4Data Overflow (a new word of data has been received before the previous word was inputted to the accumulator)
3Framing Error (data word has no valid stop bit)
2Parity Error (received parity does not agree with selected parity)
1X-mitter Buffer Empty (the previous data word has been X-mitted and a new data word may be outputted)
0Input device Ready (a ready pulse has been sent from the device)

Here’s the breakdown of how that translates to the set sio port instructions. The first command sets up the control port:

set sio port=/0/00/01/00/f/00/f
PORTThe two ports are 0 and 1 (as given by the table below). A snippet of the altairz80 SIO source gave me the clue that there are separate addresses for the control port (0) and the data port (1).
set sio port=00/0//01/00/f/00/f
READWhich bits are set when the device is ready for reading? Bit 0 is set low (0), therefore this entire field is zero.
set sio port=00/0/00//00/f/00/f
NOT READWhich bits are set when the device is not ready for reading? That is the inverse of the above, ie bit 0 set high (1).
set sio port=00/0/00/01//f/00/f
WRITEWhich bits are set when the device is ready for writing? Bit 7 is set low (0), therefore this entire field is zero.
set sio port=00/0/00/01/00/f/00/
DATAThis is not a data port, hence f for False.

And the second command sets up the data port:

set sio port=/0/00/00/00/f/00/t
PORT    This is the data port (1). According to the 88-SIO manual, data ports are odd-numbered.
set sio port=01/0/00/00/00/f/00/
DATAThis is a data port, hence t for True.

This was all done using the SIO Rev 1-compatible image (patched by Mike Douglas), but you could theoretically use the original SIO Rev 0-compatible image, provided you found the right SIO port settings for altairz80.

Loading 8K BASIC ’78 (altairz80)

First, convert the image using hex2bin.py (similar to 8K BASIC 3.2):

% cd ~/tmp
% PYTHONPATH=intelhex-2.2.1 python intelhex-2.2.1/scripts/hex2bin.py ~/z80pack-1.36/altairsim/basic8k78.hex ~/altsw/8kbas78.bin
% cd ~/altsw

Then make a new SIMH script for it. The trick here is to set the load and execute address to 0x100:

% cat << EOF > bas878
heredoc> reset cpu
heredoc> set cpu 8080
heredoc> set cpu noitrap
heredoc> set cpu altairrom
heredoc> set sio ansi
heredoc> set sio upper
heredoc> l 8kbas78.bin 100
heredoc> g 100
heredoc> EOF
% altairz80 bas878

Altair 8800 (Z80) simulator V3.9-0
8493 bytes [34 pages] loaded at 100.


11704 BYTES FREE

BASIC, Version of 02/03/78
START

OK
* [Control-E]
Simulation stopped, PC: 0011E (PUSH H)
sim> exit
Goodbye
% 

You can see that it’s 0x100 by examining the HEX file (address marked in red):

% head -1 ~/z80pack-1.36/altairsim/basic8k78.hex
:2000C39B21C36107DB10E602CA060179D311C9DB10E601C8DB1137C9C9C9C5D5E5CD07

altair (SIMH)

The first Altair 8800 emulator written for SIMH, simply called altair is a bit simpler than altairz80. The documentation for altair is also somewhat sparse. It seems that this emulator hasn’t been updated recently; the last material change to the source was around April 2012, about six years ago at the time of this writing.

However, using information gained from experiences with altairsim and altairz80, it’s possible to get altair to boot various versions of Altair BASIC and, with a patch, even make it somewhat usable.

Loading 4K/8K BASIC 4.0

Generally speaking, altair starts up with the options you need, thus the SIMH script is quite short:

% cd ~/altsw
% cat << EOF > abas440
heredoc> set 2sio ansi
heredoc> l 4kbas40.bin
heredoc> g 0
heredoc> EOF
% cat << EOF > abas8
heredoc> set 2sio ansi
heredoc> l 8kbas.bin
heredoc> g 0
heredoc> EOF
% altair abas440

Altair 8800 simulator V3.9-0
3833 Bytes loaded.

MEMORY SIZE? [Enter]
TERMINAL WIDTH? [Enter]
SIN? Y
62156 BYTES FREE
4K BASIC 4.0
COPYRIGHT MITS 1976
OK
[Control-E]
Simulation stopped, PC: 001627 (JZ 1623)
sim> exit
Goodbye
% altair abas8

Altair 8800 simulator V3.9-0
8192 Bytes loaded.

MEMORY SIZE? [Enter]
TERMINAL WIDTH? [Enter]
WANT SIN-COS-TAN-ATN? Y

59012 BYTES FREE
ALTAIR BASIC REV. 4.0
[EIGHT-K VERSION]
COPYRIGHT 1976 BY MITS INC.
OK
[Control-E]
Simulation stopped, PC: 002530 (ANI 1)
sim> exit
Goodbye
% 

All is not well, however, in BASIC land. Begin entering a program and you’ll soon see:

OK
10 DIM X(10)
20 PRINT
LIST

10 IM X(10)
20 RINT
OK

Hmmm. Looks like the first character of each line has the high bit (0x80) set. But isn’t set 2sio ansi supposed to take care of that?

The answer is: yes. However, it seems that the ansi option was created in the altair emulator without actually implementing it!

Patching SIMH altair to support the set 2sio ansi option

Apply the following patch to the altair_sio.c file, and the set 2sio ansi will do what it is supposed to do:

% diff -u altair_sio.c{.orig,}
--- altair_sio.c.orig	2012-03-25 11:51:14.000000000 -0700
+++ altair_sio.c	2018-03-09 22:38:54.000000000 -0800
@@ -207,7 +207,7 @@
         sio_unit.u3 = sio_unit.u3 > 0xFE;
         return (sio_unit.buf);
     } else {
-        sim_putchar(data);
+        sim_putchar(sio_unit.flags > UNIT_ANSI ? data & 0x7f : data);
     }
     return 0;
 }

Recompile it, etc, and then:

OK
10 DIM X(10)
20 PRINT
LIST

10 DIM X(10)
20 PRINT
OK

Et voilà !

Problems pasting text into BASIC

I’ve noticed that, with the SIMH altair emulator, pasting code into BASIC can be a bit flaky. Generally the more complex a line is, the more likely the following line is to be missing characters at the beginning.

For example, if you paste lines 260 and 270 from Hunt the Wumpus (4K BASIC edition), you can see it in action:

OK
260 LET M(J)=INT(1+RND(1)*20)
0 NEXT J
LIST

0 NEXT J
260 LET M(J)=INT(1+RND(1)*20)
OK

Although I pasted 260 and 270, the ‘27’ part was chopped off. The statements execute out of order and, if there had been a line 0, it would’ve been clobbered.

Google says that iTerm2 on OS X / macOS can be used to slow down pastes. Probably other terminals do similar things. My suggestion, though, would be to just use altairz80 instead.

Loading 8K BASIC ’78 (altair)

As with altairz80, the trick to getting BASIC ’78 to load is to put it at location 0x100 (octal 400):

% printf 'd pc 400\nl 8kbas78.bin\ng 400\n' > abas878
% altair abas878

Altair 8800 simulator V3.9-0
8493 Bytes loaded.


11704 BYTES FREE

BASIC, Version of 02/03/78
START

OK
* [Control-E]
Simulation stopped, PC: 000436 (PUSH H)
sim> exit
Goodbye
% 

Note the slightly different syntax to load binary data at an arbitrary position in memory; you deposit an address into the PC manually, then load.

As far as I can tell, ’78 BASIC doesn’t do funny things with the high-order bit. It also plays nice with altair when pasting text.

Loading 1.0/3.2 BASIC

[Still an unsolved mystery, I’m afraid. I think for BASIC 1.0, you’d have to patch BASIC to use 2SIO, as the SIO Rev 0 and Rev 1 boards are not available in altair. For BASIC 3.2, setting sense switch 11 ought to do the trick, but does not. Requires more cogitation…]

Sense switches and SIO variants

There were three things that helped me to understand the purpose of the sense switches for I/O board configuration:

Here’s a close-up shot of the Altair 8800 sense switches:

Altair 8800 sense switches

Depositing decimal 8 (octal 10) into the sense register causes 11 to go high. And, according to the tables within the help file for Altair32, this tells 4K BASIC that a 2SIO board is present:

BASIC Configuration Settings (4K BASIC)
HardwareTerminal SwitchesOctal ChannelStatus Bits ActiveOctal Masks
SIOA, B, C (not Rev 0)(none)0, 1low1/200
acra156, 7low1/200
SIOA, B, C (Rev 0)a140, 1high40/2
88-pioa130, 1high2/1
4pioa1220, 21high100/100
2sioa11 (A10 up=1stop; down=2stop)20, 21high1/2

Note: Use the “ACR” setting when loading the paper tape or cassette using the toggle loader. Once BASIC starts then change the sense switches to the 2sio position.

Here is the table for 8K BASIC:

BASIC Configuration Settings (8K and Extended BASICs)
HardwareSense Switch SettingTerminal SwitchesLoad SwitchesChannels/Device (octal)
2sio0(none)(none)20, 21 (2 stop bits)
2sio1a12a820, 21 (1 stop bit)
sio2a13a90, 1
acr3a13, a12a9, a86, 7
4pio4a14a1040, 41, 42, 43
pio5a14, a12a10, a84, 5
hsr6a14, a13a10, a946, 47
non-standard terminala14(none)(none)
no terminala15(none)(none)

Note: Use the “ACR” setting when loading the paper tape or cassette using the toggle loader. BASIC will automatically start without having to change the sense switches to the 2sio position.

Notice that, according to the Altair32 help file, switch 11 is unused for 8K BASIC. [This needs some verification.]

Altair BASIC

BASIC versions

Some BASIC programs