Copyright Information and License

CODE OWNERSHIP

If you want to take pieces of code out of the Altair32, feel free. If you take large parts of code, the contributors to the project should be given a bit of credit for their work; including it in a comment in the code itself would be nice. Please drop me a line if you make use of the code from this project as I like knowing if somebody found it useful. I've done the same with some of the code I borrowed from other emulation projects.

Should you feel motivated to improve the emulator in a major way, or even a minor way, that you think would be of interest to other Altair32 users, please let me know and I'll integrate your changes (if I also think it is useful to a larger audience) to the "official" source code base.

I should also mention that I tried to build a faithful emulation of a real machine, not an emulation of a souped-up one that could have never existed "in the day."

LEGAL STUFF

The code remains copyright of the author and the other contributors individually (but not collectively). If contributed code contains a copyright notice, the copyright to such code shall remain with the original author or authors except to the extent that modifications are required, then the copyright to such modifications shall belong to the author thereof. The author has made all reasonable efforts to attribute contributions to the Altair32 Emulator project in this help file in addition to related source file(s).

Although the author has made a reasonable effort to ensure that the emulator works as advertised, the Altair32 Emulator has absolutely no warranty, either express or implied, and the author makes no representation or warranty of merchantability or fitness for a particular purpose. In no event shall the author be liable for any damages whatsoever (including without limitation, damages for loss of business profits, business interruption, loss of business information, or any other pecuniary loss) arising out of the use of or inability to use the Altair32 Emulator. This is a hobbyist project after all...


Credits

The Altair32 project is the product of the efforts of several people. My greatest thanks goes out to this group of dedicated hobbyists without whom the Altair32 project wouldn't have been as successful:

  • Claus Giloi: The Microsoftie that wrote the initial version of the emulator.
  • Scott LaBombard: Continual regression testing; ROM configuration; data exchange; creation of disk images.
  • Joe Forgione: Updated main front panel and disk drive graphics and code to support new disk drives; VT100 control code handling; updated configuration dialogs.
  • Anthony Wood: Original Windows Console plug-in.
  • Theo Pozzi: TCP/IP console code and plenty of testing on the 8080 core.
  • Darren Gillis: Initial testing on the revised 8080 core.
  • Jim Battle: The Altair Integrated Debugger borrowed from his Solace Sol-20 emulator project.
  • Rodger Smedley: The consummate bug catcher...
  • Fred Scipione: LCC-Win32 compatibility; additional VT100 control codes.


Exchanging Data with the Emulator

by Scott LaBombard and Fred Scipione. Additional comments by Richard Cini.

Introduction

We initially set out to develop a Windows-based utility to directly manipulate the disk images. After some initial design work, we concluded that the best way to manipulate the disk images and maintain data integrity was by using the native operating system, meaning CP/M running within the emulator itself. We may still develop a Windows-based tool, but ensuring the integrity of the disk image will take some time.

There are a couple of methods that can be used to get CP/M programs into Altair32. The trick is to first convert the executable into a text-format file of some kind. The suggested format to use is Intel Hex. I use this format for several reasons:

  • There are a variety of utilities available for the PC that handle Intel Hex format files.
  • The format provides for content error checking/validation.
  • It is the format created by the CP/M assembler and used by the CP/M loader to create executables.

When considering a DOS/Windows based utility to convert the CP/M binary to an Intel Hex formatted file, you need to ensure that the utility provides a means to specify the offset of the resulting Hex file. Many such utilities will convert a binary and assume that the resulting Hex file starts at address 0h. However, CP/M programs typically are loaded from disk to the Transient Program Area (TPA) which begins at 100h. As such, you will need to find a DOS/Windows utility that enables you to specify the 100h start address for the Hex file that is created.

Now that we have an appropriate file format, we need to consider one other key element: how to do we get the file onto the Altair32 disk image? Probably the best approach here is to use a terminal emulation program with Altair32 that has the ability to send text files as if the content was typed on the console.

Examples

Here are four example methods that can be utilized to get an executable into the Altair32 environment:

Example 1 (the easiest)

The CP/M disks include two CP/M utilities called read.com and write.com. Using the emt_traps feature of the emulator, these programs import and export directly to/from the CP/M environment and the "files" subdirectory on the host machine. Each utility takes a single command line parameter -- the name of the file to import or export.

For example, typing the following at the CP/M prompt will move the file "read.com" from CP/M to the host machine:

A>write read.com

Typing the following at the CP/M prompt will move the file "write.com" from the host machine to the CP/M disk:

A>read write.com

Example 2

For the purposes of this example, it is assumed that the following tools are used:

> The Intel Hex conversion utility is bin2hex.com available at: http://www.keil.com/download/docs/bin2hex.zip.asp

> The terminal emulation program is HyperTerm (as included with Windows)

> The CP/M utility (already on the Altair32 boot disks) loadihex.com

Now follow these steps ...

  • Assume that we have a CP/M executable on our PC called 'fname.com' and we want to move it into the Altair32 CP/M environment.
  • Open a DOS Window and enter "bin2hex /o0x100 fname.com fname.hex". This will convert the binary into an Intel Hex file. Note the option that forces the resulting Hex file to begin at address 100h.
  • Within the Altair32 CP/M environment enter "loadihex fname.com". You will see a prompt to begin sending data.
  • Select the "Transfer" menu item in HyperTerm and then the "Send Text File ..." menu item.
  • In the resulting File Open dialog, insure that the "Files of type ..." drop down menu is set to view "All Files" ...and then select the Hex file that you created in step 2.
  • In CP/M, you will eventually see a message indicating "Writing data to file ..." and in a second or two you will be back at the CP/M command prompt.

You now have a copy of fname.com on your disk image!

Example 3

For the purposes of this example, it is assumed that the following tools are used:

> The Intel Hex conversion utility is bin2hex.com available at: http://www.keil.com/download/docs/bin2hex.zip.asp

> The terminal emulation program is HyperTerm (as included with Windows)

> The CP/M utility pip.com

> The CP/M utility load.com

Now follow these steps ...

  • Assume that we have a CP/M executable on our PC called 'fname.com' and we want to move it into the Altair32 CP/M environment.
  • Open a DOS Window and enter "bin2hex /o0x100 fname.com fname.hex". This will convert the binary into an Intel Hex file. Note the option that forces the resulting Hex file to begin at address 100h.
  • In CP/M enter "pip fname.hex=con:[h]". The '[h]' option tells Pip to expect data in Intel Hex format. Pip will validate the data accordingly.
  • Select the "Transfer" menu item in HyperTerm and then the "Send Text File ..." menu item.
  • In the resulting File Open dialog, insure that the "Files of type ..." drop down menu is set to view "All Files" ...and then select the Hex file that you created in step 2. You will see data transfer...but only on a single line. Each new line over-writes the last on the console, but not in the resulting hex file.
  • When all data appears to have transferred, enter Ctrl-Z (press the Control key [Ctrl] and the [Z] key at the same time). This indicates the end of the data stream to Pip...and it will then terminate.
  • In CP/M enter "load fname". In a few seconds you will see some address messages and a records written indicator, and then you will be back at the CP/M prompt.

You now have a copy of fname.com on the disk image!

Example 4

For the purposes of this example, it is assumed that the following tools are used:

> The Intel Hex conversion utility is bin2hex.com available at: http://www.keil.com/download/docs/bin2hex.zip.asp

> The terminal emulation program is HyperTerm (as included with Windows)

> The CP/M utility ed.com

> The CP/M utility load.com

Now follow these steps ...

  • Assume that we have a CP/M executable on our PC called 'fname.com' and we want to move it into the Altair32 CP/M environment.
  • Open a DOS Window and enter "bin2hex /o0x100 fname.com fname.hex". This will convert the binary into an Intel Hex file. Note the option that forces the resulting Hex file to begin at address 100h.
  • In CP/M enter "ed fname.hex"
  • Enter the editor command 'I' and then press Enter. This puts the CP/M editor in input mode.
  • Select the "Transfer" menu item in HyperTerm and then the "Send Text File ..." menu item.
  • In the resulting File Open dialog, insure that the "Files of type ..." drop down menu is set to view "All Files" ...and then select the Hex file that you created in step 2.
  • When all data appears to have transferred, enter Ctrl-Z (press the Control key [Ctrl] and the [Z] key at the same time). This exits input mode in Ed.
  • Enter the editor command 'E' to save all data and exit Ed.
  • In CP/M enter "load fname". In a few seconds you will see some address messages and a records written indicator, and then you will be back at the CP/M prompt.

You now have a copy of fname.com on the disk image!

Example 5 (courtesy of Fred Scipione)

It is possible to to import and export files for CP/M without using a TCP/IP console. The files to transfer must fit into the TPA (Transient Program Area) memory region under CP/M. Larger files can of course also be transferred by breaking them into suitably sized chunks for transfer, then concatenating the transferred pieces together again with PIP[b] (under CP/M) or COPY /b (under PC-DOS, etc.).

To import a binary file (say, mload.com) into a CP/M directory, first copy or rename it under DOS to have a .bin extension ("copy mload.com mload.bin"). Note the file's size and round it up to a whole number of 256 byte pages. At 2,816 bytes, mload.bin requires 11 pages. After CP/M is running on the emulator, use the emulator's "File/Read Image File" command to load the binary file at address 0x100. Loading will stop the CPU, so toggle the run switch. Next, in the CP/M console window issue the command "save 11 b:mload.com" (adjust the number of pages, disk designator, and file name as needed, of course). This method also works with suitable .hex format files that have a load address at 0x100. Note that a file need not be a CP/M .com file to be a binary file. Binary data files and text files (including .hex files) can be imported without any translation by giving them a .bin extension. The method may add an extra 128 byte record of "garbage" at the file end (besides any required padding of the CP/M file's last record).

To export a CP/M file, load the file into memory with the DDT command (e.g. "ddt b:mload.com"). Note the end and start addresses reported by DDT (NEXT = 0C00; PC = 0100). Use those addresses with the emulator's "File/Write Image File" command to export the file content in binary (or hex) format to a DOS file. Again, re-start the CPU by toggling the run switch.


Using the Integrated Debugger

Introduction

    While the Altair32 is running, if the user hits <F5> (function key 5), the following debugger window will pop up. In the diagram below, each of the subwindows of the debugger is labeled, and will be described in more detail in subsequent sections. The five subwindows are

  • register subwindow
  • stack subwindow
  • disassembler subwindow
  • log subwindow
  • command subwindow

    At the end there is a brief note on breakpoints.

    The scrollbars that appear in three of the subwindows behave like normal Win32 scrollbars, except as noted. The thumb of a scrollbar can be dragged to reposition the window contents; clicking on the up/down arrows of a scrollbar scrolls the window by one line; clicking above or below the scrollbar thumb causes the window contents to scroll up or down by a screenful. If a given subwindow has input focus, achieved performing some mouse command (such as clicking) in the window, the keyboard interface to the scrollbar also works. That is, the up/down arrows scroll the window by one line; the page up/page down keys scroll the subwindow by one page.

    Note that although the entire window can be resized, the relative portions of the subwindow are fixed by program logic (that is, you can't resize the subwindows independently).

Register subwindow

The register subwindow shows the current state of all the 8080 registers any time the emulation is halted. It is automatically updated after each single step or other state change. This subwindow is grayed out while the emulator is running the 8080 processor.

The value for each register is given in two forms. The first form lists the register contents in hex (either 8b or 16b), the second form after the second '=' is the value in decimal. The flags register is somewhat different, in that the second form shows which flags are set mnemonically: S=sign, Z=zero, H=half carry, C=carry, P=parity.

Tick is the current emulated 8080 cycle count; it currently is not working.

This window is read-only. To modify the contents of a register, use the SET command via the command subwindow.

Stack subwindow

The stack subwindow shows the region of memory surrounding the stack pointer, SP. The display shows 16-bit words, all even/odd aligned with the current SP value. The entry that corresponds to the top of stack (TOS) is shows highlighted in yellow. This subwindow is grayed out while the emulator is running the 8080 processor.

The region of memory being viewed can be manipulated in the usual ways via the scrollbar, or if the window has input focus, by the standard keyboard interface. As an extension of normal behavior, the HOME key can be used to scroll the window such that the TOS is visible.

Although this window automatically centers the display on the current TOS when the debugger is invoked, the window can be scrolled to any location in the 64K memory space. To make the scrolling fast, when the thumb is dragged, the window isn't updated; instead a small 4-digit hex number is shown, and the display is updated when the thumb is released.

The window is read-only. To modify the contents of the stack, or more generally any memory location, use the ENTER, EB, or EA commands via the command subwindow.

Disassembly subwindow

The disassembly subwindow is used to display the program in memory using standard Intel 8080 mnemonics. If the instruction corresponding to the current PC is in the window, it is displayed with yellow highlighting, as shown above. This subwindow is grayed out while the emulator is running the 8080 processor.

Using standard Windows scrollbar behavior, the user can change the region being displayed in the window. As an extension of normal windows scrollbar behavior, if the window has input focus, hitting the HOME key causes the display to scroll such that the line containing the current PC is positioned in the window.

Because updating the display is slow, dragging the thumb on the vertical scrollbar doesn't immediately scroll the display. Instead, a four-digit hex display is shown of which area of memory will be displayed when the thumb is released.

Note that scrolling backwards or jumping to an arbitrary starting location is problematic. This is because 8080 instructions can be one, two, or three bytes long. For example, when scrolling back one line, going back one byte might be a valid one byte opcode, or it might be the immediate data of a two-byte or three-byte instruction. The debugger uses a heuristic to try and get a reliable "sync"; it goes back 10 instructions or so and disassembles forward. If the address of interest falls in the middle of an instruction in the resulting stream, it is assumed that the immediately preceding instruction start is the true instruction boundary. Although it works is most cases, the heuristic isn't foolproof, so be warned that this may happen if the disassembly seems goofy.

Note that two of the instructions have a red circle in the left column. A solid red circle (at $C02B, above) means that there is an active breakpoint on that instruction. A hollow red circle (at $C034, above) means that there is a disabled breakpoint on that instruction.

Breakpoints can be entered, listed, and manipulated via the command line interface, but this window provides a few shortcuts as well.

  • Holding down the CTRL key and left-clicking on a line causes a breakpoint to be set on that line. If there is already an active breakpoint on the line, it is disabled; if there is already a disabled breakpoint on that line, the breakpoint is killed (deleted).
  • Double left clicking on a line causes a temporary breakpoint to be set on the line and 8080 execution is resumed until the line is reached or another breakpoint is encountered, whichever comes first.
  • Right clicking on a line causes a pop-up menu to appear with a few choices; some choices will be grayed-out based on context:
  • Add breakpoint
  • Disable breakpoint
  • Enable breakpoint
  • Kill breakpoint
  • Run to PC
  • Home current PC

The integrated 8080 debugger supports source code overlays. These are simply the .PRN files that are output by the standard CP/M ASM and MAC assemblers. Whenever a .HEX file is loaded from the main menu, the debugger looks in the same directory for a file with the same root name but with a .PRN suffix. If it is found, it is "autoloaded" as a source code overlay. Optionally, a user can manually load a source code overlay via the debugger command line interface via the "OVerlay" command. In either case, the OVerlay command has many forms which can be used to control how overlay information is managed and used.

Below appears three snippits of the disassembler window with different overlay modes enabled. In the "on" mode, whenever the debugger needs to disassemble at a given instruction, it checks to see if there is a source code overlay matching that address. If there is a match, then the source code file is displayed. If there is no match, the line is just mechanically disassembled. In the "off" mode, it is as if there is no overlay in memory. In the "both" mode, if there is a source code overlay for a given address, it is displayed (but in gray) and the line is also mechanically disassembled.

In either "on" or "both" modes, the bytes of memory corresponding to the source line are compared against the actual memory contents. If they don't match, the source line is still printed, but it appears as red text instead of black.

Above: "overlay on"

Above: "overlay off"

Above: "overlay both"

More than one overlay can be in memory at one time. If one address has a match in more than one overlay, the most recently loaded or refreshed overlay is the one shown. In the cause of autoloaded overlays (i.e., those loaded implicitly as the result of loading a .hex file from the main menu), the overlay system can elect to dispose of an overlay if too little of the overlay is meaningful. Manually loaded overlays stay in memory until explicitly purged.

The overlay command takes many form so it is best to type "help overlay" in the debugger to get the rundown.

Log subwindow

The log subwindow shows a history of commands that the user has typed in and the debugger responses. The user input is echoed with a grayed background to help distinguish commands from responses.

500 lines of history are maintained; lines older than that simply vanish. There is currently no way to log the output to a file, nor to copy a selection from the window.

The vertical scroll bar appears whenever there are enough lines in the command history to warrant it. The scrollbar responds to the typical scrollbar behavior: the window may be scrolled up/down a line/page at a time by clicking on the up/down arrows are above/below the thumb; the thumb can be dragged. If the log subwindow has input focus, which is achieved by clicking in the window or by manipulating the scrollbar, then the scrollbar responds to standard keyboard scrolling behavior. The up/down arrow keys move the display up/down one line; the up/down page keys scroll the display a page at a time. Typing the HOME key causes the window to scroll such that the last entry becomes visible.

Command subwindow

The command subwindow accepts debugger commands from the user; a command is interpreted when the ENTER key (carriage return) is hit.

50 lines of command history are maintained; commands older than this are simply discarded. The user can access older commands via the up/down arrows; up-arrow corresponds to moving to older commands. To prevent tediously scrolling past commands which have been repeated, the command history mechanism will show a given command only once when scrolling up or down through the command history.

Note that some of the mouse command shortcuts in the disassembler subwindow "stuff" phantom commands into the command subwindow to cause the specified actions to happen.

A brief rundown of the debugger commands can be had at any time in the debugger by typing

help

without any arguments. Here is a key to interpreting the following table of commands:

  • <foo> means that foo isn't literal, just descriptive of what the argument is.
  • Things in square brackets, like [foo], means it is an optional argument.
  • Ellipses (...) means that there can be a number of subsequent arguments.
  • Command names can be abbreviated in many cases; below the necessary part is shown in caps, while the optional part is in lower case and inside parentheses.
  • Numeric arguments are hex by default, but this can be overridden to be decimal by starting the number with a "#" character.
  • The command line is case insensitive except for the string arguments to the EA and LA commands.

Here, then, is the list of commands:

memory commands:
   DB  <start> [<end>]         dump bytes
   DW  <start> [<end>]         dump words
   DA  <start> [<end>]         dump ascii
   EB  <start> aa bb ...       enter bytes (also EN(ter))
   EA  <start> abcde...        enter ascii
   FILL <start> <end> <bb>      fill block
   LB  <start> <end> aa bb ... locate bytes
   LA  <start> <end> abcde...  locate ascii
   MM  <start> <end> <dest>    move memory
   CM  <start> <end> <dest>    compare memory
   SM  <start> <end> aa bb ... show matching bytes
   DASM <start> [<end>]        disassemble
   LOAD <fname>                load .hex binary file
   SAVEH <start> <end> <fname>  save binary to .hex file

execution commands:
   RESET                        reset uP
   N(ext)   [<nnnn>]           step over n ops
   S(tep)   [<nnnn>]           step in n ops
   EX(ecute) [<nnnn>]           continue execution
   C(ont)   [<nnnn>]           synonym for EX
   SET <reg> <nnnn>             modify register
   INC(lude) <filename>         perform a file of commands

breakpoint commands:
   TO   aaaa                   run to PC=aaaa
   BP(c) aaaa                   break PC=aaaa
   BR(b) aaaa [dd [mm]]         break read byte addr=aaaa, data=dd,  mask=mm
   BRW  aaaa [dddd [mmmm]]     break read word addr=aaaa, data=dddd, mask=mmmm
   BW(b) aaaa [dd [mm]]         break write byte addr=aaaa, data=dd,  mask=mm
   BWW  aaaa [dddd [mmmm]]     break write word addr=aaaa, data=dddd, mask=mmmm
   BI(n)  aa [dd [mm]]         break in port=aa, data=dd, mask=mm
   BO(ut) aa [dd [mm]]         break out port=aa, data=dd, mask=mm
   BL(ist)   [<nn>]            breakpoint list   all/nn
   BD(isable) [<nn>]            breakpoint disable all/nn
   BE(nable) [<nn>]            breakpoint enable all/nn
   BK(ill)   [<nn>]            breakpoint remove all/nn

misc commands:
   KEY <nn>                     force a keystroke
   H(elp) [<cmd>]               command summary
   EXIT | X(it)                 close debugger

There is a detailed command description for each debugger command, accessed by typing

help <command>

Brief note on breakpoints

There are two types of breakpoints: PC breakpoints, and data breakpoints (read byte, read word, write byte, write word, in, and out). It should be noted that PC breakpoints are triggered before the instruction at the specified address is executed, while data breakpoints occur after the instruction that triggered the breakpoint is executed.


Using Disk Images

Floppy disks provided fast and nearly unlimited access to data and programs in 330k chunks. Unfortunately the initial cost was staggering. The MITS floppy disk system, which included the two-board controller, one 8" disk drive and an enclosure cost a budget-busting $1,200 in kit form or $1,700 for an assembled version. Demand for high-capacity storage options, higher manufacturing volumes and the introduction by Shugart Associates and Tandon of more cost effective 5-1/4" "mini-floppy" drives helped foster the growth of floppy disks as the preferred storage medium.

Since the Altair32 Emulator does not have the benefit of being physically connected to a real 8" floppy drive, we simulate the drive by using images of real disks -- a fairly common feature of any machine emulator. These disk image files are straight binary copies, in ascending track and sector order, of original disks. Several disk images are provided, including CP/M 2.2, Altair DOS and Microsoft Disk BASIC.

The Altair32 Emulator supports up to eight concurrent floppy disk images. When using Altair DOS or Microsoft Disk BASIC, all eight emulated drives are standard 8" Pertec FD-400 hard-sectored disk drives. When booting CP/M, the capacity of the emulated disk drive depends on which CP/M disk image is booted. If the user boots with the regular CP/M image (Cpm22.dsk), the first four slots (CP/M drives A through D) represent standard Pertec drives and the remaining four slots (CP/M drives E through H) represent custom drives that support "large" disks (disks with a capacity of just over 1MB each).

Conversely, if the user boots with the high-density CP/M image (Cpm22HD.dsk), the first four slots (CP/M drives A through D) represent custom drives that support "large" disks and the remaining four slots (CP/M drives E through H) represent standard Pertec drives. If the user attempts to attach a disk of a density that doesn't match the expected density based on the booted CP/M image, CP/M will throw a BDOS error on that drive.

In order to use a disk image with the Altair32, you first have to "attach" it to the emulator. Selecting Disk Management from the File menu pops-up a window with a picture of the original Altair 88-DSK drive. At the top of the window, there is a drop-down list box that enables the user to select the drive to work with. To the right are two icon buttons for attaching and detaching disk images. Further to the right is an area which shows the name of the disk image file attached to each respective simulated disk drive. The user may also click on the drive door latch to attach and detach buttons. Audible and visual feedback is given to the user using sound samples from a real Altair disk drive. Slot 0, of course, is the boot drive.

After a disk is attached to Slot 0, it may be booted by running the MITS bootloader ROM. This code is built into the emulator itself and resides in the top 256 bytes of the Altair32 memory space. So, to boot the drive, toggle the address 0xff00 into the front panel and toggle RUN. If there is no disk attached to drive 0 or the image is non-bootable, the Altair32 will prototypically crash, requiring the user to toggle RESET. If there is a problem while booting a disk, the console screen fills with the letter "C" for a sector checksum error. A screen full of the letter "M" indicates that it is unable to write sector data to current memory location (equivalent to a memory write protect error). A screen full of the letter "O" indicates an overlay error, meaning that the code being loaded has overlaid the loader itself.

Sample Disks

Several disk images are included with the distribution so that the new user can jump in and start using the Altair32 Emulator. All of the disk images are booted according to the directions above. The disk images included in the base distribution are:

Altair DOS Version 1.0 (altdos.dsk)

A very simple disk operating system and system monitor that was long promised but not delivered until it was almost irrelevant. A short tour will reveal it to be a dog; far inferior to CP/M. When booting Altair DOS, make sure that all of the sense switches are set to OFF after setting PC to the bootrom (toggle 0xff00, hit EXAMINE, toggle the sense switches OFF, then hit RUN). Otherwise, Altair DOS will not boot. The following is a sample session:

MEMORY SIZE? [return]
INTERRUPTS? N [return]
HIGHEST DISK NUMBER? [3 return] (3 here = 4 drive system)
HOW MANY DISK FILES? [3 return]
HOW MANY RANDOM FILES? [2 return]

056449 BYTES AVAILABLE
DOS MONITOR VER 1.0
COPYRIGHT 1977 BY MITS INC
.[MNT 0]

.[DIR 0]

DOS monitor commands:
COP program copier (like CP/M "pip")
LOA load
RUN run
REN rename
DEL delete
MNT mount
DSM dismount
DIR directory
SAV save
DIN format

Devices:
TTY console
HSR {unknown}
FDS disk

MITS Disk Extended BASIC Version 4.1 (mbasic.dsk)

This was the commonly used software for serious users of the Altair computer. Equivalent to 12k Extended BASIC but self-booting, it is a powerful (but slow) BASIC with some extended commands to allow it to access and manage disks. Boot it according to the instructions above except that you need to set the sense switches according to the console port settings -- A12 and A8 must be in the UP position. The following is a sample session:

MEMORY SIZE? [return]
LINEPRINTER? [C return] (C=Centronics lineprinter)
HIGHEST DISK NUMBER? [0 return] (0 here = 1 drive system)
NUMBER OF FILES? [3 return]
NUMBER OF RANDOM FILES? [2 return]

44041 BYTES FREE
ALTAIR BASIC REV. 4.1
[DISK EXTENDED VERSION]
COPYRIGHT 1977 BY MITS INC.
OK
[MOUNT 0]
OK
[FILES]

CP/M 2.2 (cpm22.dsk): Standard density disk image of the standard CP/M 2.2 distribution and includes a few more utilities and programs, including development tools, and configured for 60k RAM systems with drives A-D as standard density, E-H as high (254 tracks) density. The 'format' utility or 'sysgen' can be used to copy boot tracks and create a new bootable disk.

CP/M 2.2 (cpm22hd.dsk): High-density CP/M 2.2 boot disk. Again, it is configured for a 60k RAM system with drives A-D as high density, E-H as low-density (the exact opposite of the above).

Blank disks are provided in both densities (sm_blank.dsk and lg_blank.dsk).

CP/M Source Code (cpmsrc.dsk): A standard density disk that contains the CP/M source modules (including bios). It must be attached to drive B if the the CP/M environment is going to be re-configured (resized, bios modified, etc.). If you wish to recompile CP/M and load it into memory in a format that is compatible with sysgen, you can modify the modules on this disk as required. A quick warning: you should never modify anything but the org statements in bdos.mac or ccp.mac, and even only when reconfiguring CP/M for a different memory size. Return to the A drive type 'do syscpm'. That will compile and load all modules, after which you will see an indication that it's okay to run sysgen to write the image to the system tracks of the disk of your choice.

Extended BASIC 5 (extbas5_1178.dsk): The last and very rare BASIC release for the Altair. It includes the original distribution files, including PIP and StarTrek.

Basic 5 "Pip" notes:

As with any MITS disk BASIC, 'mount 0' first. Then use 'files' to see the files on the disk. Then 'load "pip"' to load it (it's just a BASIC program). Then "run"... the commands to enter at the prompt are:

SRTx - where x is the drive number...lists a sorted directory
DIRx - provides a directory listing of the specified drive
LISx,fname - lists the file contents of fname on drive x
COPx,y - will copy disk from drive x to drive y
INIx - will initialize the specified disk in drive x
DATx - will prompt for a track number, and sector number and will dump (in octal) the sector contents

Also included is a slightly earlier version of Extended BASIC, edbas5-_0778.dsk. It is probably the next-to-last release of Disk BASIC 5.

Demos (demos.dsk): This disk contains a few BASIC demo programs that highlight the capabilities of the VT100 terminal support, including color.

PL/M-80 (plm0.dsk and plm1.dsk): This isn't the real Intel ISIS, but it's an interface between real ISIS programs and CP/M...sort of an ISIS emulator that runs on top of CP/M. These disks are not compatible with other Altair disks, so they have to be booted separately. The Altair32 should be configured for maximum RAM (i.e., top of RAM set to 0xfeff). Additional disks can be made by copying the disks using the Windows Explorer. New users should read README.DOC on disk0 and COMPILE.DOC on disk1. These disks were derived by an anonymous contributor from the MPM II source code from the Digital Research archive at http://www.retroarchive.org/cpm/archive/unofficial/source.html.


Other information and Links

The following other documents are available:

  • Original documentation for CP/M version 2.2
  • Microsoft BASIC-80 Quick Reference
  • Microsoft BASIC-80 Reference Manual
  • Microsoft M-80 Macro Assembler manual
  • Microsoft Link-80 manual
  • Microsoft CREF-80 Cross-reference utility manual
  • Microsoft LIB-80 Librarian manual
  • MITS Turnkey Monitor quick reference
  • TASM , a table-based cross-assembler. This is what the author uses in developing 8080-based software for the emulator (offsite link).
  • Intel 8080 Instruction Set description with op-code matrix (offsite link; 4.5mb)
  • Intel 8080 Microprocessor Datasheet (offsite link; 7.1mb)
  • Commercial CP/M Archive at retroarchive.org.
  • Oak CP/M Archive (Oakland is off-line; this is a mirror in Germany.)
  • Intel Binary-to-Hex conversion utility from Kiel Software.


Loading and Running the BASIC Interpreter

Original BASIC distributions were generally provided on paper tape which were loaded into the Altair by using a small (approximately 20 byte) program loader program that was toggled into the front panel. Later distributions were made on cassette and diskette as those hardware devices became more widely adopted. Paper tape software was recorded in the MITS Absolute Tape Format. The cassette versions were essentially magnetic representations of the paper tape, being recorded in the Absolute Tape Format, too.

As time wore on, many more hardware devices became available. And so began the nightmare of trying to configure BASIC to work with specific models of hardware. Luckily, Microsoft tried to build some intelligence into each subsequent version of BASIC so that with a flip of a front panel switch, BASIC would know which port to use for various I/O devices.

The toggle boot loader was a small program that read the paper tape or cassette into memory and ran the tape-resident loader, which completed the loading and initialization of BASIC. Below are the configuration tables, reproduced from MITS documentation, that shows the various load and run options.

BASIC Configuration Settings (4K BASIC)
Hardware | Terminal Switches | Octal Channel | Status Bits Active | Octal Masks
SIOA, B, C (not Rev 0) | {none} | 0, 1 | low | 1/200
acr | a15 | 6, 7 | low | 1/200
SIOA, B, C (Rev 0) | a14 | 0, 1 | high | 40/2
88-pio | a13 | 0, 1 | high | 2/1
4pio | a12 | 20, 21 | high | 100/100
2sio | a11 (A10 up=1stop; down=2stop) | 20, 21 | high | 1/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.

BASIC Configuration Settings (8K and Extended BASICs)
Hardware | Sense Switch Setting | Terminal Switches | Load Switches | Channels/Device (octal)
2sio | 0 | {none} | {none} | 20, 21 (2 stop bits)
2sio | 1 | a12 | a8 | 20, 21 (1 stop bit)
sio | 2 | a13 | a9 | 0, 1
acr | 3 | a13, a12 | a9, a8 | 6, 7
4pio | 4 | a14 | a10 | 40, 41, 42, 43
pio | 5 | a14, a12 | a10, a8 | 4,5
hsr | 6 | a14, a13 | a10, a9 | 46, 47
non-standard terminal | a14 | {none} | {none}
no terminal | a15 | {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.

Loading BASIC from Paper Tape

The first step in loading a paper tape image is to load the small bootstrap loader program. This 21-byte program loads the tape image and jumps to an initialization routine in the image which is responsible for loading the balance of BASIC and beginning execution.

Here are the basic steps for loading 4k BASIC:

  • Load the 4k toggle loader into the emulator memory using the File menu.
  • Set the address toggles to 0 and hit RESET.
  • From the File menu, open the PTP device. Load the 4k BASIC tape into the reader.
  • Raise A15, the ACR sense switch and click RUN.
  • When the tape counter stops, BASIC will be running but with a bad terminal configuration bit (since A15 was raised)
  • Halt the system and lower all of the address toggles.
  • Raise A11, the 2SIO sense switch. This tells BASIC to use the 2SIO card at port 20Q for the console.
  • Click RUN.

At this point, you can connect your telnet client to the emulator. If you selected the "Windows Console" option, the console would pop-up at this point. If using the serial option, you should see the BASIC sign-on screen.

When loading other versions of tape BASIC, the steps are similar, just substitute the proper sense switch settings for those above. The distribution files contain pre-compiled toggle loaders for the various versions of paper tape and cassette BASICs.

When BASIC starts, it will ask several configuration questions:

MEMORY SIZE?

To which you should normally respond with the <ENTER> key. If you want, you can enter the actual top of memory (in decimal) if for some reason you want BASIC to only see part of your memory. To the next questions (if asked; varies by version), the following are safe answers:

TERMINAL WIDTH?	(80 for 80 column)
WANT SIN? (4K BASIC; Y/N)
WANT RND? (4K BASIC; Y/N)
WANT SQR? (4K BASIC; Y/N)
WANT SIN/TAN/COS/ATN? (8k/extd; Y/N depending on if you want trig functions)
LINEPRINTER? C (for Centronics C700 printer; O for MITS 88-LPR)
HIGHEST DISK DRIVE NUMBER? 0
NUMBER OF FILES? 5
NUMBER OF RANDOM FILES? 3

Sample Programs

Several sample BASIC programs are included with the emulator. Some of these were the most common (and maddingly simple) programs first used by a new Altair owner. Others are perennial favorites such as Lunar Lander, Hunt the Wumpus and StarTrek.

Of course, before loading a BASIC program, one needs to have a BASIC interpreter loaded. Four different versions of BASIC are generally available: 4k BASIC, 8k BASIC, Extended BASIC 4.0 (12k BASIC), Extended BASIC 5.0, and Disk Extended BASIC. The first four were distributed on paper tape and the fourth on a bootable diskette. As is customary in the software industry, as time went on and hardware resources (principally RAM) became more plentiful, the programs grew to add more features. The 4k BASIC is very functional but very simplistic -- 26 one-letter variables and no string manipulation functions. 8K was a good all-around BASIC. The Extended BASICs and Disk BASIC were the top of the line BASICs for those who could afford the RAM and the floppy disk subsystem.


Microsoft BASIC Reference

  • Introduction to the Microsoft BASIC Interpreter
  • Special Characters
  • Variable Type Declaration Chars
  • Commands
  • Edit Mode Subcommands
  • Program Statements (except I/O)
  • PRINT USING Format Field Specifiers
  • String Specifiers
  • Input/Output Statements
  • Operators
  • Arithmetic Functions
  • String Functions
  • I/O and Special Functions
  • Reserved Keywords by Version
  • Interpreter Error Codes

    • Introduction to the Microsoft BASIC Interpreter

    This HELP File is derived from the "Microsoft BASIC Reference Manual", and covers the basics of the language. For more detail and instruction, refer to the manual itself.

    The Microsoft BASIC Interpreter is booted as follows: On the Altair's front panel, set the leftmost 8 switches all up, and the others all down. Left EXAMINE, then put all the switches down. Be sure the BASIC disk is in drive 0, and the drive is ready. Then, depress the RUN switch. BASIC should boot up and ask:

    MEMORY SIZE?

    To which you should normally respond with the enter key. If you want, you can enter the actual top of memory (in decimal) if for some reason you want BASIC to only see part of your memory. To the next questions, the following are safe answers. Refer to the manual for details:

    LINEPRINTER? C (for Centronics C700 printer; O for MITS 88-LPR)
HIGHEST DISK DRIVE NUMBER? 0
NUMBER OF FILES? 5
NUMBER OF RANDOM FILES? 3

    Altair BASIC will print its OK prompt, letting you know it's ready for your commands.

    Special Characters

    ^C        Interrupts program execution and returns to MBASIC
^G        Rings bell at terminal
DEL       Deletes last char typed
^I        Tab (every 8)
^O        Halts/resumes program output
^R        Retypes the line currently being typed
^S        Suspends program execution
^Q        Resumes execution after ^S
^U,^X     Deletes line being typed
CR        Ends every line being typed in
LF        Breaks a logical line into physical lines
ESC       Escapes Edit Mode Subcommands
.         Current line for EDIT, RENUM, DELETE, LIST, LLIST commands
&O,&      Prefix for Octal Constant
&H        Prefix for Hex Constant
:         Separates statements typed on the same line
?         Equivalent to PRINT statement

    Variable Type Declaration Characters

    $    String              0 to 255 chars

%    Integer             -32768 to 32767

!    Single Precision    7.1 digit floating point

#    Double Precision    17.8 digit floating point

    Commands

    Command   Syntax                        Function

AUTO      AUTO [line][,inc]             Generate line numbers
CLEAR     CLEAR [,[exp1][,exp2]]        Clear program variables;  Exp1 sets
                          end  of memory and Exp2 sets amount
                          of stack space
CONT      CONT                          Continue program execution
DELETE    DELETE [[start][-[end]]]      Delete program lines
EDIT      EDIT line                     Edit a program line
FILES     FILES [filename]              Directory
LIST      LIST [line[-[line]]]          List program line(s)
LLIST     LLIST [line[-[line]]]         List program line(s) on printer
LOAD      LOAD filename[,R]             Load program; ,R means RUN
MERGE     MERGE filename                Merge prog on disk with that in mem
NAME      NAME old AS new               Change the name of a disk file
NEW       NEW                           Delete current prog and vars
NULL      NULL exp                      Set num of NULLs after each line
RENUM     RENUM [[new][,[old][,inc]]]   Renumber program lines
RUN       RUN [line number]             Run a prog (from a particular line)
RUN       filename[,R]                  Run a prog on disk
SAVE      SAVE filename[,A]             Save prog onto disk;  ,A saves prog
                                    in ASCII
TROFF     TROFF                         Turn trace off
TRON      TRON                          Turn trace on
WIDTH     WIDTH [LPRINT] exp            Set term or printer carriage width;
                          default is 80 (term) and 132 (prin)

    Edit Mode Subcommands

    A         Abort -- restore original line and restart Edit
nCc       Change n characters
nD        Delete n characters
E         End edit and save changes; don't type rest of line
Hstr[ESC] Delete rest of line and insert string
Istr[ESC] Insert string at current pos
nKc       Kill all chars up to the nth occurrance of c
L         Print the rest of the line and go to the start of the line
Q         Quit edit and restore original line
nSc       Search for nth occurrance of c
Xstr[ESC] Goto the end of the line and insert string
[DEL]     Backspace over chars; in insert mode, delete chars
[CR]      End edit and save changes

    Program Statements (except I/O)

    Statement Syntax                        Function

CALL      CALL variable [(arg list)]    Call assembly or FORTRAN routine
DEF       DEF FNx[(arg list)]=exp       Arith or String Function
          DEF USRn=address              Define adr for nth assembly routine
          DEFINT range(s) of letters    Define default var type INTeger
          DEFSNG "        "   "         "         "     "   "   Single
          DEFDBL "        "   "         "         "     "   "   Double
          DEFSTR "        "   "         "         "     "   "   String
DIM       DIM list of subscripted vars  Allocate arrays
END       END                           Stop prog and close files
ERASE     ERASE var [,var ... ]         Release space and var names
ERROR     ERROR code                    Generate error code/message
FOR       FOR var=exp TO exp [STEP exp] FOR loop
GOSUB     GOSUB line number             Call BASIC subroutine
GOTO      GOTO line number              Branch to specified line
IF/GOTO   IF exp GOTO line [ELSE stmt ... ]
          IF exp <> 0 then GOTO
IF/THEN   IF exp THEN stmt[:stmt] [ELSE stmt ... ]
          IF exp <> 0 then ... else ...
LET       [LET] var=exp                 Assignment

MID$      MID$(string,n[,m])=string2    Replace  a  portion of string  with
                              string2; start at pos n for m chars
NEXT      NEXT var[,var ... ]           End FOR
ON ERROR  ON ERROR GOTO line            Error trap subroutine
GOTO	  GOTO line
ON/GOSUB  ON exp GOSUB line[,line]      Computed GOSUB
ON/GOTO   ON exp GOTO line[,line]       Computed GOTO
OUT       OUT port,byte                 Output byte to port
POKE      POKE address,byte             Memory put
RESTORE   RESTORE [line]                Reset DATA pointer
RESUME    RESUME or RESUME 0            Return from ON ERROR GOTO
          RESUME NEXT                  Return to stmt after error line
          RESUME line                  Return to specified line
RETURN    RETURN                        Return from subroutine
STOP      STOP                          Stop prog and print BREAK msg
WAIT      WAIT prot,mask[,select]       Pause until input port [XOR select]
                              AND mask <> 0

    PRINT USING Format Field Specifiers

    Numeric Specifiers Specifier Digits Chars Definition # 1 1 Numeric field . 0 1 Decimal point + 0 1 Print leading or trailing sign - 0 1 Trailing sign (- if neg, SP otherwise) ** 2 2 Leading asterisk $$ 1 2 Floating dollar sign; placed in front of leading digit **$ 2 3 Asterisk fill and floating dollar sign , 1 1 Use comma every three digits ^^^^ 0 4 Exponential format _ 0 1 Next character is literal

    String Specifiers

    Specifier               Definition

  !                        Single character
  /SPACES/                 Character field; width=2+number of spaces
  &                        Variable length field

    Input/Output Statements

    Statement Syntax/Function

CLOSE     CLOSE [[#]f[,[#]f ... ]]
           Close disk files; if no arg, close all
DATA      DATA constant list
           List data for READ statement
FIELD     FIELD [#]f,n AS string var [,n AS string var ...]
           Define fields in random file buffer
GET       GET [#]f[,record number]
           Read a record from a random disk file
INPUT     INPUT [;] [prompt string;] var [,var ...]
          INPUT [;] [prompt string,] var [,var ...]
           Read  data from the terminal;  leading semicolon suppresses echo
           of  CR/LF and semicolon after prompt string causes  question
           mark  after prompt while comma after prompt suppresses  question
           mark
KILL      KILL filename
           Delete a disk file
LINE      LINE INPUT [;] [prompt string;] string var
INPUT      Read an entire line from terminal; leading semicolon suppresses
           echo of CR/LF
          LINE INPUT #f,string var
           Read an entire line from a disk file
LSET      LSET field var=string exp
           Store data in random file buffer left-justified or  left-justify
           a non-disk string in a given field
OPEN      OPEN mode,[#] f,filename
           Open a disk file; mode must be one of --
               I = sequential input file
               O = sequential output file
               R = random input/output file
PRINT     PRINT [USING format string;] exp [,exp ...]
           Print data at the terminal using the format specified
          PRINT #f, [USING format string;] exp [,exp ...]
           Write data to a disk file
          LPRINT [USING format string;] var [,var ...]
           Write data to a line printer
PUT       PUT [#] f [,record number]
           Write data from a random buffer to a data file
READ      READ var [,var ...]
           Read data from a DATA statement into the specified vars
RSET      RSET field var = string exp
           Store  data  in  a random file buffer right justified  or  right
           justify a non-disk string in a given field
WRITE     WRITE [list of exps]
           Output data to the terminal
          WRITE #f, list of exps
           Output data to a sequential file or a random field buffer

    Operators

    Symbol   Function

 =        Assignment or equality test
 -        Negation or subtraction
 +        Addition or string concatenation
 *        Multiplication
 /        Division (floating point result)
 ^        Exponentiation
 \        Integer division (integer result)
MOD       Integer modulus (integer result)
NOT       One's complement (integer)
AND       Bitwise AND (integer)
OR        Bitwise OR (integer)
XOR       Bitwise exclusive OR (integer)
EQV       Bitwise equivalence (integer)
IMP       Bitwise implication (integer)
=,>,<,    Relational tests (TRUE=-1, FALSE=0)
  <=,=<,
  >=,=>,
  <>

The precedence of operators is --
 1.  Expressions in parentheses     8.  Relational Operators
 2.  Exponentiation                 9.  NOT
 3.  Negation (Unary -)            10.  AND
 4.  *,/                           11.  OR
 5.  \                             12.  XOR
 6.  MOD                           13.  IMP
 7.  +,-                           14.  EQV

    Arithmetic Functions

    Function     Action

ABS(exp)       Absolute value of expression
ATN(exp)       Arctangent of expression (in radians)
CDBL(exp)      Convert the expression to a double precision number
CINT(exp)      Convert the expression to an integer
COS(exp)       Cosine of the expression (in radians)

CSNG(exp)      Convert the expression to a single precision number
EXP(exp)       Raises the constant E to the power of the expression
FIX(exp)       Returns truncated integer of expression
FRE(exp)       Gives memory free space not used by MBASIC
INT(exp)       Evaluates the expression for the largest integer

LOG(exp)       Gives the natural log of the expression
RND[(exp)]     Generates a random number
                 exp <0 seeds new sequence
                 exp =0 returns previous number
                 exp >0 or omitted returns new random number

SGN(exp)       1 if exp >0
               0 if exp =0
               -1 if exp <0
SIN(exp)       Sine of the expression (in radians)
SQR(exp)       Square root of expression
TAN(exp)       Tangent of the expression (in radians)

    String Functions

    Function     Action

ASC(str)       Returns ASCII value of first char in string
CHR$(exp)      Returns a 1-char string whose char has ASCII code of exp
FRE(str)       Returns remaining memory free space
HEX$(exp)      Converts a number to a hexadecimal string
INPUT$(length [,[#]f])
               Returns a string of length chars read from console or from a
               disk file; characters are not echoed

INSTR([exp,]str1,str2)
               Returns  the first position of the first occurrence of  str2
               in str1 starting at position exp
LEFT$(str,len) Returns leftmost length chars of the string expression
LEN(str)       Returns the length of a string
MID$(string,start[,length])
               Returns chars from the middle of the string starting at  the
               position  specified  to the end of the string or for  length
               characters

OCT$(exp)      Converts an expression to an Octal string
RIGHT$(str,len)
               Returns rightmost length chars of the string expression
SPACE$(exp)    Returns a string of exp spaces
STR$(exp)      Converts a numeric expression to a string
STRING$(length,str)
               Returns  a string length long containing the first  char  of
               the str
STRING$(length,exp)
               Returns  a string length long containing chars with  numeric
               value exp
VAL(str)       Converts  the  string  representation of  a  number  to  its
               numeric value

    I/O and Special Functions

    Function     Action

CVI(str)       Converts a 2-char string to an integer
CVS(str)       Converts a 4-char string to a single precision number
CVD(str)       Converts an 8-char string to a double precision number

EOF(f)         Returns TRUE (-1) if file is positioned at its end
ERL            Error Line Number
ERR            Error Code Number
INP(port)      Inputs a byte from an input port
LOC(f)         Returns next record number to read or write (random file) or
               number of sectors read or written (sequential file)
LPOS(n)        Returns carriage position of line printer (n is dummy)

MKI$(value)    Converts an integer to a 2-char string
MKS$(value)    Converts a single precision values to a 4-char string
MKD$(value)    Converts a double precision value to an 8-char string

PEEK(exp)      Reads a byte from memory location specified by exp
POS(n)         Returns carriage position of terminal (n is dummy)

SPC(exp)       Used in PRINT statements to print spaces
TAB(exp)       Used in PRINT statements to tab to specified position

USR[n](arg)    Calls the user's machine language subroutine with the arg

VARPTR(var)    Returns address of var in memory or zero if var has not been
               assigned a value
VARPTR(#f)     Returns the address of the disk I/O buffer assigned to  file
               number

    Reserved Keywords by Version

    RESERVED WORDS (all versions)

    CLEAR, DATA, DIM, END, FOR, GOSUB, GOTO, IF, INPUT, LET, LIST, NEW, NEXT,

    PRINT, READ, REM, RETURN, RUN, STOP, TO, TAB, THEN, USR

    RESERVED WORDS (8K, Extended, and Disk versions)

    (all the above words plus) AND, CONT, DEF, FN, NOT, NULL, ON, OR, OUT, POKE, SPC, WAIT

    RESERVED WORDS (Extended and Disk versions)

    (all the above words plus) AUTO, CONSOLE, DEFDBL, DEFINT, DEFSNG, DEFSTR, DELETE,

    EDIT, ELSE, ERASE, ERL, ERR, IMP, INSTR, LINK, KL, LPRINT, MOD, RENUM,

    RESUUME, SPACE$, STRING$, SWAP, TROFF, TRON, VARPTR, WIDTH, XOR

    RESERVED WORDS (Disk BASIC)

    (all the above words plus) CLOSE, DSKI$, DSKO$, FIELD, FILES, GET, KILL, LOAD,

    LSET, MERGE, MOUNT, NAME, OPEN, PUT, RSET, UNLOAD.

    Interpreter Error Codes

    Code Error                      Code Error

  1  NEXT without FOR               14  Out of string space
  2  Syntax error                   15  String too long
  3  RETURN without GOSUB           16  String formula too complex
  4  Out of data                    17  Can't continue
  5  Illegal function call          18  Undefined user function
  6  Overflow                       19  No RESUME
  7  Out of memory                  20  RESUME without error
  8  Undefined line                 21  Unprintable error
  9  Subscript out of range         22  Missing operand
 10  Redimensioned array            23  Line buffer overflow
 11  Division by zero               26  FOR without NEXT
 12  Illegal direct                 29  WHILE without WEND
 13  Type mismatch                  30  WEND without WHILE

Disk Errors --

Code Error                      Code Error

 50  Field overflow                 58  File already exists
 51  Internal error                 61  Disk full
 52  Bad file number                62  Input past end
 53  File not found                 63  Bad record number
 54  Bad file mode                  64  Bad file name
 55  File already open              66  Direct statement in file
 57  Disk I/O error                 67  Too many files

    Document source: Portions from the Online Software Museum. Reformatted for use with the Altair32 Emulator.


starting the emulator

Using the Emulator

A microcomputer front panel ("FP") may look different from manufacturer to manufacturer, but several elements are common -- lights and switches. Early FP-based computers, such as the PDP-8, used discrete light bulbs as indicators. It wasn't until the prices of light emitting diodes ("LEDs") dropped sufficiently did they become the choice for use in FPs. Other FP designs, such as the PDP 11/34a and the Heath H-8, used a "programmers console" consisting of a hexadecimal keypad and pseudo alpha-numeric display using a common 7-segment LED display.

The Altair used C&K toggle switches and discrete T1-3/4 red LEDs. The front panel of the Altair32 looks like this:

The functions of the switches are as follows:

  • Address and data switches: enable the user to toggle address and/or data values into the 8080 memory
  • RUN/STOP: starts and stops execution at the current program counter ("PC")
  • Single Step/Slow: enables executing the instruction at the current PC either one at a time or slowly (about 25% of normal speed)
  • Examine/ExNext: allows looking at the data at the address indicated by the address switches. Using ExNext automatically steps the PC to the next address. So, with all address switches down, click Examine to see the contents of address 0. Click ExNext to see the contents of address 1, etc.
  • Deposit/DepNext: Similar to "examine" except that the data toggled on the data switches will be stored at the location specified by the address switches. Next automatically steps the address.
  • Reset: resets the Altair and tests the FP display.
  • External Clear: resets external bus devices.
  • Protect/Unprotect: write-protects the memory.

The FP also has several LED status indicators, as follows:

  • PROTECT: Memory is write protected.
  • INTE: Interrupt Enable. Reflects the status of the internal interrupt flip-flop. May be set/reset by the EI/DI CPU instructions. The flip-flop is automatically reset during state T1 of the instruction fetch cycle (M1) or upon a CPU reset.
  • WAIT: Acknowledges that the CPU is in the WAIT state.
  • HLDA: Hold Acknowledge. Appears in response to the transition of the HOLD pin (pin 13) of the 8080 CPU and indicates that the data and address buss will go into the hi-impedance state. HLDA is active in state T3 for memory read or port input, or in the clock period following the T3 state for a memory write or port output. In either case, the HLDA signal appears after the rising edge of the phase-2 clock.
  • Status indicators. During T1 of the bus cycle, the 8080 puts 8 bits of status information on the data bus which indicates what operation is in progress in the current bus cycle. In a real Altair, this information would be latched by an 8-bit latch and displayed on these indicators. The indicators are as follows: MEMR (memory read), INP (input operation), M1 (opcode fetch), OUT (output operation), HLTA (the HLT instruction was encountered and acknowledged), STACK (a stack operation), *WO (memory write), INT (interrupt).
  • Data and address LEDs: these LEDs reflect the values on the data bus and address bus, respectively.

Getting Started

Double-click the Altair32 icon to start the emulator. When you start the emulator for the first time, it is setup for a base configuration of 60k of RAM, 4k of ROM and using the telnet protocol as the console access method. Also by default the 88-DSK boot ROM is loaded into the upper 256 bytes of the address space. See Configuring the Emulator Memory for a discussion of how to configure the memory space and loaded ROMs.

Changes to the emulator configuration can only be performed when the emulator is "off" since changes directly affect the memory space and console I/O.

If you are going to use the Altair32 Emulator in front panel mode, you don't need to do anything more. The emulator is fully functional.

Now, you're ready to run BASIC or boot one of the included diskette images. See the sections titled Loading and Running the BASIC Interpreter and Using Disk Images, respectively.

Entering Programs

In the beginning, programs were toggled into the front panel and then lost when the Altair was turned off. This may have been fine when the memory size was only 256 bytes, but add a 4k SRAM board and it becomes impossible from the time perspective to toggle in a program.

So, many people had a paper tape reader/punch or when available, a cassette interface. Although these alternative methods took some time -- the equivalent to 10bps for the tape and a relatively speedy 300bps for the cassette -- it was certainly much faster than toggling. Adding floppy disk drives was the Holy Grail of speed enhancements for these machines.

When developing the original version of BASIC for the Altair, Bill Gates and Paul Allen used a cross-assembler to generate the paper tapes used as the distribution medium. This cross-assembler, a program running on a computer with a different microprocessor than the one on which the target computer is based, ran on a PDP-10 in Harvard's computing lab.

A similar process is used in developing non-BASIC programs for use with the Altair32 Emulator. BASIC programs are still written, saved, and loaded within the emulator just as if the user was sitting at a real Altair. Writing machine language programs for the Altair32 can be accomplished two ways.

First, one could use M80 (Microsoft Macro-assembler for the 8080) or another 8080-based assembler running within the emulator. This method, again, is like using a real Altair to write software. To some extent this is easier within the Altair32 Emulator because the user can "cut and paste" a text file containing source code into the edit screen of the assembler by using this feature of many telnet client programs.

Alternatively, one could use a PC-based cross-assembler for the 8080 processor such as TASM (Squak Valley Software's Telemark table-based cross assembler) or any number of shareware/freeware assemblers. These programs produce either a binary object file or an Intel HEX-formatted file, both of which can be loaded into the emulator.

Loading and Saving Programs

For machine language programs, the Altair32 supports files in both binary of Intel HEX formats. Loading files is performed from the Load File Image option under the File menu. Selecting this command brings up a dialog box that enables the user to browse for the file and identify the starting location for the file (for BIN-type files only). Intel HEX-format files are embedded with the address information, so the user does not have to specify the starting location.

When the user hits OK, the file is loaded into the emulator memory at the specified starting address. The emulator automatically determines, based on load address, if the program is a RAM file or a ROM file.

The process is similar for saving a file. The user browses for the file to save and then prompted for the starting address and length. Clicking OK saves the file.

Of course, one could toggle a program into the front panel and save the memory using the "save file" process mentioned above.

BASIC versions 8K and higher have CLOAD and CSAVE commands which can save BASIC programs to paper tape or audio cassette. You can also capture the listing using the screen capture feature in any telnet client or in the Windows Console.

Using the Altair32 Front Panel

For information on the Altair32 Front Panel, go here. The only thing to note when using the Front Panel is that it must be connected to a USB port on the host computer before you start the emulator. Otherwise, the emulator will not recognize that the Front Panel is connected.


Documentation for the Turnkey Monitor

by Scott LaBombard

The Altair PROM Monitor is a recompiled version of the MITS Altair Turnkey Monitor. If you load the ROM to fd00h and while in CP/M type 'mon', you will be dropped into the monitor. To go back to CP/M you can enter 'J000000' which will warm boot back to CP/M, or 'J177400' which will cold boot CP/M (177400q = ff00h).

Operation of the Altair PROM Monitor

The Altair PROM Monitor has three commands:

M - Memory examine and change
D - Memory dump
J - Jump to user program

a) The M command

The M command allows the user to examine and change any location in the Altair 8800 memory. The form of the M command is as follows:

Mxxxxxx

where xxxxxx represents from zero to six valid octal digits. The PROM Monitor opens the location specified and displays the three-digit octal contents of that location. The Monitor then waits for three valid octal digits. Three complete octal digits must be input; the space character cannot be used as a delimiter in this case. When this valid data has been received, the Monitor attempts to place the data into the opened location. Once the deposit has been made and verified, the M function closes the current location and opens the following location. If the user tries to deposit information into nonexistent memory, ROM, or protected RAM, the bad deposit causes "?" to be printed on the terminal and control is returned to the Monitor. Assuming a valid deposit, this sequence continues until a non-valid character (any character except the digits 0-7) is input. This non-valid character is flagged with a "?" and control returns to the Monitor. This is the normal way to return to the Monitor. If a space is input instead of a valid octal character, the M function closes the present location without making any changes and then opens the next consecutive location. While the M command is looking for input, the space character may be used at any time to close the current location without change, and open the following location. Therefore, even though one or two valid octal digits may have been input, when the space has been received, the location is closed without change. To deposit new data, three complete valid octal digits must be input.

b) The D command

The D command allows the user to dump the contents of the Altair 88OO's memory between any two locations. The D command has the following form:

Dxxxxxx xxxxxx

To use the D command, type a D in response to the Monitor's prompt character. The D function will then wait for the starting address (zero to six valid octal digits). If six digits are input, the D function prints a space and then waits for the ending address (zero to six valid octal digits). The ending address must be greater than or equal to the starting address. If less than six digits are input during the starting address, the D function echoes the delimiting space character, but does not print one of its own. Once the D function has received valid starting and ending addresses, it displays the memory contents as octal data, 16 bytes per line. Upon completion of the dump, the D function performs a carriage return and line feed and then returns to the Monitor.

c) The J command

The J command allows the user to transfer control between the monitor and another program. The J command has the following form:

Jxxxxxx

where xxxxxx is the starting address of the user routine (zero to six valid octal digits). Once the J function has received a valid address, it will load the program counter with the address and start execution of the user program at that address.

Memory Space and Stack Considerations

The PROM Monitor is 256 decimal or 377 octal bytes long and is assembled to operate with a starting address of 176400 octal. It must be located at this point in memory or it will not operate correctly. The PROM Monitor establishes a stack with a top address of 176000 octal when it is entered. The Monitor never has more than four levels of subroutine calls at anyone time, so only eight bytes are actually used in the stack. The stack itself usually resides in the 1k of RAM that is, on an Altair 8800n Turnkey system, part of the Turnkey Module. It is the user's responsibility to see that there is RAM available at the stack location. Otherwise, the Monitor cannot operate correctly, if at all. All necessary registers and the stack pointer should be saved before jumping from a program to the Monitor, since the Monitor destroys the contents of the stack pointer and all registers upon entry. Restoration of the registers must be handled by the user's program.

Error Considerations

Errors in data input can be corrected easily before the last character is typed. Simply type a non-octal character (except space) and the monitor will print a question mark and a period. The command may then be typed again. When the octal input routines are requesting input, they do not check for over-range conditions on the input data. For example, when using the M function, three complete valid octal digits must be input in order to deposit new data into a memory location. Since the Altair 8800 is organized around an eight bit byte, the largest valid octal number that can be input is 377. In fact, 777 can be input without the Monitor detecting an error. The actual value that is deposited in the memory location in that case is not equal to 777 octal, but depends upon the binary representation of the most significant digit input to the routine. For example, 477 causes the routine to deposit octal 077 into the memory location. The same possible error condition is present when addresses are input, except that the maximum value that may be typed is 1777777. Anything larger will not be flagged as an error, but the effective address will depend upon the binary representation of the highest order digit.


Using the Line Printer

Clearly it's handy having a printer attached to a computer to capture output from various programs. Printers of the late-70s were typically 80-column or 132-column formed-character ("Daisy Wheel") or dot-matrix style printers using continuous-page "tractor-feed" paper. Print one character or hundreds, the printer would dutifully print just that. This is called character-oriented printing.

Modern inkjet and laser printers, those that are primarily used with Windows, are page-oriented printers. The Windows printer driver formats the printed data and sends it to the printer. The printer then holds the data in its memory until it has rendered a full page and prints it one page at a time. If there's less than one-page of data, a form feed can force its printing.

Because of this difference, the Altair32 Emulator can't directly emulate a character-oriented printer because of how Windows and modern printers handle printing. The compromise is to capture any output destined for the printer in a text file for the user to print later. Obviously the text file won't properly capture the output of certain types of programs such as graphics programs or programs that produce custom fonts. This support may be added in a future release of the Altair32 Emulator although I'm not sure that much software of that type existed for the early S-100 machines.

The line printer is represented by the following dialog:

The printer is "turned on" through the Activate Line Printer command in the File menu. The Attach button enables the user to enter the filename of a file which will be used to capture the printed data. Turning the printer "off", closing the emulator or selecting Detach will flush the printed data to the file and close it. The line printer connects to the emulator through ports 2Q/3Q, the MITS standard for the 88-LPC controller.


History of the Altair32 Emulation Project

In late-1997 I began my hobby of collecting and restoring "classic" computers. Like many others in this hobby, I began working with the computers that I learned BASIC programming on -- the Commodore PET and the Radio Shack TRS-80 Model I. I began collecting machines, software programs and documents with the thought that without some preservation efforts, these historical assets would be lost for future generations. Also, I believed that a better perspective on current computing performance could be gained by my children if they could experience what I experienced as a teenager in 1980.

As I gained more experience in the hobby, I began expanding my collection beyond the early microcomputers I used in school to include other examples of early personal computing. I added to the collection a multitude of early single-board computers. Then, I came across the world of S-100 computers from the late-1970's and began collecting some prime examples from that period.

After reading several books about the development and growth of Microsoft, and selecting Microsoft as my B-School business case, I decided I wanted to obtain a MITS Altair. During the "dot com" boom and subsequent years, these became unobtainable for a reasonable price, so I had no real expectation of ever owning one.

Then, in 1999 I came across the binaries for an Altair 8800b emulator which was written by Claus Giloi. I thought that his emulator would be great to experience what it was like to use a front-panel based machine.

Well, the original implementation didn't work well as a computer since, according to Claus, it was designed in 1991 to be more "blinkenlignts" than a fully-functional emulator. In early 2000, I finally found the source code for it on the Web. I contacted Claus and he basically said that he didn't have time to improve it or actually verify that it worked as a true machine emulator. For Claus, the project basically went dormant development-wise in late-1996.

Claus built the emulator from the magazine article and the data books -- nothing else. He had no software or a physical Altair to work with. The original emulator supported no additional hardware...no disks, no console, no way to get programs into or out of it. The CPU code was about 80% functional, but it's the old "80/20" rule...the last 20% was the hardest to fix.

So, Claus gave me the go-ahead to take over the project, and I jumped right in. The first modifications were done on June 8, 2000 and have been followed by a steady stream of improvements and enhancements.

I still hope to one day own a real Altair 8800.


Prototypical Hardware Specifications

The specifications of a typical Altair 8800 setup might have been as follows:

CPU | Intel 8080, 2.0MHz. 8 software interrupts, one hardware interrupt, 64k address space, port-mapped I/O. Three CPU voltages (+5, +12, -5 VDC).
Memory | Static or dynamic RAM, 300ns access time. 4k was the practical minimum for use with BASIC. The Altair was delivered initially with 256 bytes. As the prices of memory declined, users expanded their systems to between 56k and 60k (leaving 4k-8k available for ROM space).
Serial ports | Two or more RS-232 or 20mA current loop, 300-9600 baud (although early modems, when available, supported only 300 baud).
Disk | 330k 8" hard-sectored floppy disk and controller

Approximate pricing for a typical Altair computer in 1976:

Base system | Case, PS, CPU card: kit $400; assembled $750
4k memory card | kit $300; assembled $450
16k memory card | kit $500; assembled $650
Two-port serial card | kit $200; assembled $300
4-port parallel I/O | kit $unknown (1 port occupied)
Cassette tape interface | kit $unknown
One diskette drive and controller | kit $1,200; assembled $1,700 (the drives themselves were about $1,000 each at the time)
ADM-3A CRT terminal | $700

So, a very respectable 32K Altair with one diskette drive and a terminal would run about $3,500 in kit form and $4,750 assembled. Many early owners bought a used Teletype ASR-33 terminal with an integrated paper tape device as used it for the console. A video display terminal (called a "glass TTY"), such as those from Lear Seigler (LSI), Hazeltine, and others was also used as a console.


Virtual Hardware Specifications

Since the Altair32 Emulator is a Windows-based emulation of the MITS Altair 8800 computer, we can take some poetic license with regards to how capable a machine is emulated . The Altair32 emulates a fully-configured 8800 system with 60k of RAM (4k of the address space is allocated for ROM usage), a paper tape punch and reader, a MITS floppy disk controller with eight Pertec 8" floppy disk drives (including a decidedly unprototypical "large" disk of about 1.1mb), a parallel line printer and a cassette tape interface. The console terminal is emulated by using a common telnet client program, Windows Console services or a real serial terminal.

The general specifications of the Altair32 Emulator is as follows:

CPU | Intel 8080, 2.0MHz (adjustable). 8 software interrupts, one hardware interrupt (unemulated at this time), 64k address space, port-mapped I/O.
Memory | 60k RAM and 4k ROM by default. Fully configurable using configuration dialog box. Buss bandwidth limitations/wait-states are not emulated, so memory access speeds are irrelevant within the emulator context.
Serial ports | Two – a MITS 2SIO dual-port card at ports 20Q-23Q (port 1 is the console and port 2 is for the paper tape punch/reader).
Disk | Qty. 8 (controller capacity is 16 drives) Pertec 330k 8" hard-sectored floppy disk drives. Controller sits on I/O ports 10Q-12Q. Disk geometry is 77 tracks of 32 sectors, each sector 137-bytes in size, resulting in an unformatted capacity of 337,664 bytes per disk. A "large disk" format is supported (254 tracks of 32, 137-byte sectors for an unformatted capacity of 1,113,536 bytes). The standard 88-DSK bootrom occupies the uppermost 256-bytes of memory and is accessed by toggling the address 0xff00 and RUNning from there.
Terminal | Terminal services provided through a telnet client resembles any number of ASCII terminals, such as the vintage ADM-3A. Using the Windows Console option results in a color DEC VT100 ASCII terminal. Using the real serial connection enables the user to connect a true terminal to the host computer. BASIC programs stored in standard text files can be pasted directly into the selected client, with the effect the same as if the user typed the program into the emulator by hand.
Line printer | MITS 88-LPC is emulated through a text file capture. Printer is "connected" to the emulator through the MITS-default addresses of 2Q/3Q.
Paper tape device | Paper tapes are emulated through file images accessed by the emulator using the paper tape punch/reader device. The PTP occupies port 2 of the 2SIO serial interface card.
Cassette device | Cassette tapes and paper tapes both used the MITS Absolute Tape Format. The virtual 88ACR interface connects to the emulator through the MITS-assigned ports 6Q/7Q.
Read-only memory | Coupled with the auto-load feature below, binary files can be loaded at emulator startup into any area of memory.
Core programs - tape | Altair BASIC 3.2 (4k), BASIC 4.0 (8k), Extended BASIC 4.0 and Extended BASIC 5.0 (the last version made) through paper tape images. Tapes are loaded using a small bootstrap loader (called the Toggle Bootloader).
Core programs – disk | CP/M 2.2, AltairDOS, Microsoft Disk Extended BASIC, Microsoft BASIC 5.0 through binary disk images.
Other | Since CP/M supports large disks, a 1.1mb CP/M hard drive image is indirectly supported.

Using the approximate cost figures from 1976, this system would cost a whopping $11,300.


Using the Paper Tape Punch/Reader

The Altair32 Emulator provides the user with the ability to use paper tape image files. A paper tape image file is a binary file that holds the contents of a paper tape including the leader characters. Many original paper tapes included several hundred characters of "nulls" or other non-meaningful characters before and after the actual program data. This enabled the tape to be loaded in the reader without missing important data. The punched leader is similar to the leader on cassette tapes which provided a measure of protection and synchronization prior to the actual data.

Interestingly, MITS used the same data format for distributing programs by paper tapes as it did for magnetic tape cassettes. The MITS Absolute Tape Format was used to distribute software on paper tape or audio cassette, the cassette effectively being a magnetic representation of the paper tape.

The emulated paper tape reader/punch device looks like this:

As you can see, the device is very simply emulated. There are two buttons to load paper tape files for either reading or writing. The Rewind button is used to "rewind the tape" to the beginning. This device can be used with the appropriate toggle loader to load any of the three paper tape versions of BASIC.

Paper tapes were used for a short time early in the life of the Altair until the faster 88-ACR audio cassette interface was released. Many users who upgraded to cassettes kept a paper tape reader around for that odd program that came from another user only on paper tape.

The preferred method of loading any of the versions of Tape BASIC included with the Altair32 is throught the Cassette Deck and the Cassette Toggle Loader. The paper tape reader is provided for use with CP/M as the native "PUN:" and "RDR" devices. This device connects to the emulator through ports 22Q/23Q.


Using the Cassette Deck

The 88-ACR audio cassette recorder device connects to the 8800 through ports 6Q/7Q. The ACR consisted of two boards: an analog board and a special version of the SIO serial board. CP/M did not support an audio cassette player/recorder as a standard device as CP/M is a disk-based operating system.

The cassette deck is represented like this in the Altair32 Emulator:

The cassette deck image is of a late-model Radio Shack CCR-81. The tape drive has six transport control buttons which are similar to those that appear on an audio cassette deck. In order, the buttons are: Stop/Eject, Rewind to the Beginning of the Tape, Rewind, Play, Record, and Fast Forward. The "rewind to the beginning of the tape" is less than prototypical but it's a convenient way to start at the beginning of the tape without unloading it.

The user loads a tape for reading by pressing Play or pressing Record to load a tape for writing. The device is designed so that it will not read and write from the same tape in the same operation. To change access modes, one has to unload and then re-load the tape. This is implemented in this fashion more as a measure of protection against overwriting tapes accidentally.

Rewind and Fast Forward are used to change the tape position in slow motion. Pressing the Stop/Eject button once halts this tape movement. Clicking it a second time will eject the tape.

The tape counter below the picture of the cassette is the tape counter and shows the actual pointer within the file (as returned from the C-library) and is not in any way related to real time (as it would be on a real cassette deck). Pressing the reset button next to the counter will reset the counter (and the file pointer) to zero.

In the section Loading and Running the BASIC Interpreter, there is a short tutorial on using the tape reader to load the included BASIC tape images as if loading from tape on the Altair.


Altair 8800 History

Altair32 Emulator for Windows

History of the Altair 8800

Anyone reading about the history of personal computers knows that the Altair was the first commercially successful hobbyist microcomputer, debuting in 1975 in kit form for only $397.00 from a small company in New Mexico, Micro Instrumentation and Telemetry Systems (MITS), which was founded in 1968. The system was introduced to the world in a January, 1975 cover article in the now-defunct Popular Electronics magazine.

The kit consisted of nothing more than printed circuit boards, a hefty enclosure, a power supply and bags of parts. Once assembled, all the machine could do is allow tiny programs to be tediously toggled in through the front panel switches into the paltry 256 bytes of memory that came as standard equipment. Usually in these written histories this is the only mention of the machine, unfortunately leaving the casual reader to believe it was a laughably limited machine that was quickly supplanted by other more capable machines. This false impression does not do justice to the hobbyist computer that ultimately changed the world.

The first machines that were sold had only four expansion slots in a chassis that could accommodate 18, and consisted of nothing more than the case, power supply, CPU board, and 256-byte memory board. A modest start, but from the beginning the system was designed to grow through expansion cards attached to the "Altair Bus". The Altair Bus was more generally known as the S-100 Bus due to the number of pins in the interface (100). The S-100 Bus later became an official IEEE standard, the IEEE-696 Bus.

Soon, MITS was offering 1K, 4K and larger memory boards, serial interfaces, and diskette drives and controllers. The performance of the early MITS-manufactured memory boards was poor, so a cottage industry of third-party suppliers sprang up. These suppliers then branched out to other peripheral boards and even complete systems. Versions of the Altair after the initial production run were shipped with full 18-slot motherboards. The original power supply was underrated and the motherboard suffered from bus noise. This too was later corrected in the Altair 8800a model. The "b" revision looked spiffy, was well designed, and overcame all the amateurism that plagued the early efforts of the tiny MITS. The initial design of the Altair in some ways reflected that it was designed by a hobbyist for hobbyists.

Software was also limited for the Altair. There was no commercial pre-packaged software industry at the time and even if there were, there was not much one could do with 256-bytes of memory. It wasn't until reliable 4k and 8k memory boards became widely available that pre-packaged software became viable. The first version of BASIC available for the Altair was 4k Tape BASIC. Even that required 8k of RAM (4k for BASIC itself and 4k of user program space).

Unfortunately, MITS' success was short-lived. Pertec Computer Corp., a large manufacturer of minicomputer components that had recently moved into the rapidly growing microcomputer field, bought MITS in May 1977. By 1978, the "Altair Bus" had become a well-entrenched standard. Pertec killed the Altair product line just over one year later in July 1978. By the early 80's, consumer demand for S-100 based machines had all but vanished, having been replaced by easier-to-use "micro-computers" from IBM, Commodore, Apple, and Tandy among others.


Configuring the Terminal Console

Clicking on the "Console" category will bring-up the terminal console configuration options. If you want to use any of the included versions of BASIC or run CP/M, AltairDOS or Microsoft Disk BASIC, you need to use some form of terminal program or a real "glass TTY" or Video Data Terminal (VDT). The default configuration uses a telnet-based solution. The second uses the Windows Console feature built into each version of Windows. The third method uses a real serial terminal connected to a serial port on the host computer.

The telnet-based console can be used with any version of Windows. Also, as a server program, one could reach the emulator over a network subnet and, with proper routing, outside the subnet. If there is no telnet client installed, several are available on the Internet, and more recent versions of Windows include an updated version of HyperTerminal that has a "TCP/IP" connection option. Avoid using the plain-jane telnet program included with Windows (telnet.exe) as it doesn't work well with the Altair32 Emulator, producing dropped characters and missing console output.

When setting-up HyperTerm, create a new connection for "localhost". In the "Connect Using" drop-down list box, select "TCP/IP" as the connection method. When the program prompts for the address to connect to, type "localhost", meaning any server on the host machine itself (Altair32, in this case). Additionally, the server port is configurable using the edit box labeled "Port". The accepted standard port is 23, but can be changed to match the port selected on the Altair32 to avoid conflicts with other software.

The Windows Console is a built-in feature of all versions of Windows from Win95 and up. Selecting this option from the console options will cause a DOS-prompt-like console window to appear on demand for console I/O services. This feature is nice because the user is not required to install and use another program.

With the convenience of the Windows Console comes one drawback. The screen buffer size is only configurable on Windows NT-based versions of the Console (Windows NT, Windows 2000, and Windows XP). Without the expandable screen buffer, the user will not be able to capture output from the emulator to paste into a file beyond the 25-line vertical screen limit. This is absolutely critical for the process of moving data into and out of the emulator space. The Windows 95-based versions of the Windows Console (Windows 98/98/ME) will work, but the console screen buffer is limited to a screen size of 80x25.

The Windows Console support code in the emulator has been updated to implement the VT100 terminal standard, providing full cursor color and positioning features to the Altair32 even though color terminals were typically not used by the average hobbyist.

The third connection is a physical serial port on the host computer. All you need do is connect a real terminal (like an LSI ADM-3 or Heath H-19) through a null-modem cable to the host PC and properly configure the port settings to match the physical hardware. For those users with real terminals, this results in the most realistic representation of an Altair.


Configuring Memory

Clicking on the "Memory" category will bring-up the memory configuration options.

The composition of the memory between RAM and ROM is fully configurable. By default, the emulator is configured with 60k of RAM and 4k of ROM. The ROM occupies the top 4k of the memory space (from address 0xf000 and up). The top 256-bytes of ROM contains the boot ROM for the 88-DSK diskette controller. Permanently-resident ROMs can be added or removed using this dialog.

The slider bar at the bottom of the dialog enables the user to specify the amount of RAM available to the emulator in 256-byte chunks starting at address 0. Alternatively, the user can specify the number of bytes of RAM in hexadecimal, decimal or octal through the Installed RAM edit box. The minimum amount of RAM is 256 bytes and the maximum is 61,440.

There is space for six permanently-installed ROM files. The first slot is generally reserved for the disk boot ROM. The Add and Remove buttons can be used to configure additional ROMs. The ROM information is stored in a private INI file located in the program root directory.

Clicking "Add" brings up an Open File dialog. The user can browse the file tree in order to select the ROM file to load. Only the loading of binary files in this fashion is supported. After selecting the file, the user is prompted to enter the starting address (in hexadecimal) of the file. Although intended for the loading of ROMs, any file can be loaded into any memory region.

To remove a ROM from the cofiguration, he user selects the file to remove from the list of installed files and selects "Remove". After confirming that this is the intended action, the file is removed from the configuration.


Configuring the Emulated CPU

Clicking on the "CPU" category will bring-up the CPU configuration options.

From this dialog, the user can configure the emulated CPU speed, which defaults to 2.04MHz. Other speed options include 1.02MHz (half-speed), 4.09MHz (2x prototypical), and "Unregulated". The Altair32 Emulator uses a multithreaded timeslice scheduler (with a 10ms timeslice) in order to reduce the host CPU load to manageable levels while maintaining prototypical emulated CPU speeds. When the "Unregulated" speed option is selected, the emulated CPU speed reported in the status bar at the bottom of the main window will vary based on the capabilities of the host machine. On the primary emulator development and test machine, the theoretical unregulated CPU speed was just over 80MHz.

Presently, the only available CPU option is the 8080 from Intel. A future release of the Altair32 Emulator will include Z80 emulation.


Configuring Other Options

Clicking on the "Other" category will allow configuring miscellaneous emulator options.

Console Bell Character: this enables or disables the console bell sound (ASCII ^G).

Word Wrap: this enables or disables automatic word wrap at column 80.

Disk Drives: this enables or disables prototypical sounds from the disk drive.

Fan Noise: this option enables or disables prototypical exhaust fan sounds that occur when the Altair is turned on or off.


Other information and links

Altair32 Emulator

Using the Cromemco Dazzler Emulation

The Cromemco Dazzler was a two-board video system for S-100 machines. One board was the video generator and the second was the host DMA interface. The screen consisted of an array of "elements" and the size could be adjusted between 32x32 to 128x128, both black and white and color.

Several games were developed for the Dazzler, and some of them required a joystick. Cromemco also produced a joystick, called the Joybox, that connected to the host S-100 machine through a third peripheral card, a 7A+D Analog/Digital board. Each Joybox consisted of an analog joystick and four buttons, and the board was capable of supporting two Joyboxes. We emulate the Joybox through the keyboard and, optionally, through a real joystick connected to the host PC.

The Files directory in the installation tree contains a folder for Dazzler Programs. In it you will find loading and running instructions for the following Dazzler games:

  • 4D Tic Tac Toe -- a tic-tac-toe game
  • Chase -- a two-person competitive game
  • Doodle -- an on-screen drawing program
  • SpaceWar -- a two-person space combatants game
  • Track -- a game of skill; follow the spiral path to the center to win
  • DazzleWriter -- a small teletypewriter
  • Gotcha! -- block your opponent with colored squares
  • Game of Life (from Popular Electronics)
  • Tankwar (Z80 only) -- two-player head-to-head tank fighting
  • Felix

The general process for loading and using Dazzler programs is as follows:

General Process
* start the Altair32
* open Dazzler screen (F7)
* load an image, say Spacewar (load/run 0000)
* run the image. Spacewar should pop right on the console.

For Spacewar (put on asbestos suit, that's a sun)
tap '=' (unshifted+) to set fast mode and to release all buttons, listen for beep
tap left/right to rotate, tap center to stop
tap 1 to shoot, tap center to stop shooting
tap up to engage thrust, tap center to disengage
hold down to pull joystick all the way back for hyperspace, tap center to release

Tap, center, tap, center, tap, center, tap...just like old flight simulators without joysticks.

Joy buttons 1234 and sticks left, right, up, down are latched (logically stay pressed). This allows for combinations of buttons and to hold the current stick position

* '=' select fast mode 'reset' (for chase, Spacewar, Tankwar) -- release all buttons and center both sticks and beeps
* '-' select slow mode 'doodle' (for doodle, track) -- release all buttons do NOT center sticks and beeps
*
* joy1 buttons 1234 joy2 buttons 1234
* keyboard -> 1234 7890
*
* E
* W R I
* joy1 stick S (D) F joy2 stick J (K) L
* X V ,
* C
*
* 'D' centers joy1 stick
* in fast mode releases button 1 (Spacewar, Tankwar fire button)
* in slow mode releases buttons 1234 (doodle colors)
*
* 'K' centers joy2 stick
* other actions same as 'D'
*
* joysticks should work with upper or lower case


Other information and links

Physical Front Panel Option

The Altair32 Emulator supports a USB-based physical front panel hardware add-on (the Altair32 Front Panel). This panel enables the emulator user to experience more closely what it is like using a real Altair.

The Altair32 Front Panel is the same physical size and layout as the original Altair 8800 (in fact, an original Altair dress panel was templated and entered into a CAD program to produce the Altair32 Front Panel). The Altair32 Front Panel contains red LEDs (bi-color optional) and an array of switches to control the emulated CPU in the same way as the prototype. The LEDs instantly reflect the status of the CPU, address and data registers, and the emulators respond instantly to the operation of the toggle switches.

The Altair32 Front Panel also has several other interesting features. The panel contains two, 3-wire RS-232C-compatible serial ports for exclusive use of the host emulator for such peripherals as a paper tape reader/punch or serial line printer. There is also an optional USB 2.0 hub controller for desktop peripheral expansion.

Further, the board contains several power supply options which, with the size of the board matching that of the original Altair, would enable the user to case mount the front panel rather than as a desktop picture frame as shown in the picture above.

The Altair32 Front Panel is made using a combination of SMT and through-hole parts. SMT components are kept to a minimum, giving the beginner the opportunity to use advanced components with a minimum of frustration.

Further information on purchasing and constructing the Altair32 Front Panel can be obtained from the project Web site.


Table of Contents

Altair32 Emulator

Table of Contents

Welcome to the Altair32 Emulator, an emulation of the MITS Altair 8800 computer from 1975. This help file includes the following topics:

  • Brief history of the MITS Altair 8800
  • Brief history of the Altair32 project
  • Project Credits
  • Starting-up and running the emulator
  • Configuring the emulator
  • Using the emulated line printer and paper tape reader/punch
  • Loading the paper tape versions of Microsoft BASIC
  • Using the emulated disk drives
  • Using the integrated debugger
  • Using the Cromemco Dazzler emulation
  • Importing files into the emulator space
  • Links to other information
  • Copyright Information and License