Recognize environment variables 'I8080ASH_ASSUME_NONBLOCK_STDIN' and 'I8080ASH_USE_STTY_MIN_TIME'
3 files changed
tree: 23fd8bd909b07ff2fcdd64cf4111da83f2bc7de3
  1. COPYING
  2. README.md
  3. c_basic.bin
  4. c_bios.bin
  5. i8080-rw.ash
  6. i8080.ash
README.md

i8080 emulator for Almquist shell

A complete Intel 8080 processor emulator with emulated UART console and disk I/O, implemented in pure Almquist shell (ash) script. This particular emulated machine is compatible with the 8080 emulator written by Oscar Toledo G. for the 19th IOCCC (2006).

Variants

2 variants of the emulator are available:

  • i8080.ash loads the specified program into memory, where the memory is implemented by 65536 individual shell variables
  • i8080-rw.ash directly reads and updates the specified memory file in-place; one example usecase is to use /dev/fb0 as memory; because every memory access runs an external hexdump(1) or dd(1) command, memory performance will be poor.

Supported shells

Any POSIX-compatible Almquist shell is supported, this excludes ancient pre-POSIX versions of Almquist shell.

GNU bash 2.0 or later is also supported, but a reduced performance is expected.

It may work with other Unix shells, but this is not guaranteed.

Primarily tested with the Almquist shell provided by FreeBSD (/bin/sh) and Debian (/bin/dash).

dash versions 0.5.7 and later, and busybox ash are known to have suboptimal performance.

Other dependencies

In addition to a supported shell, some other basic external commands are required by the emulator:

  • dd(1)
  • hexdump(1) or xxd(1)
  • sed(1), if xxd(1) is being used
  • grep(1)
  • perl(1)
  • stty(1), if using from a terminal (the usual case)

Supporting files

Usage

Both variants accept a single path name to the memory image file. Because i8080-rw.ash updates the memory image file in-place, it is recommended to first duplicate the memory image file, when trying out this variant.

If environment variables A, B, C, D, E, H, L, SP, PC and FLAGS are set to appropriate values, they will used for as the initial values of the respective registers to start emulation; this can be used to restore a previously interrupted emulation.

When running the emulator, pressing Ctrl-C will giving a menu for different actions. If you choose to dump registers and terminate emulation, you will be able to restore this emulation state by setting the register values in environment variables, as described above.

Configuration environment variables

In addition to the environment variables for restoring a emulation state, the emulator also recognize some environment variables that configure how it interact with the host operating system.

I8080ASH_USE_BASH_READ

If you run the emulator with GNU bash, set this to a non-empty string to make it using the built read command with some bash-specific options, rather than dd(1), to read the input key. This can make the emulator to work on a system without perl(1).

Obviously this is only useful with bash, otherwise it is ignored.

I8080ASH_ASSUME_BASH

Normally the emulator avoid uses of any bash-specific feature if the underlying shell is not bash. However if you believe your shell supports the bash-specific features that would be used by the emulator, you may set this environment to a non-empty string, to make the emulator to assume that it is bash.

Currently only meaningful when used together with I8080ASH_USE_BASH_READ.

I8080ASH_USE_DD_IFLAG_NONBLOCK

Set this to a non-empty string to make the emulator passing iflag=nonblock for the dd(1) command line that used to read the input key, in attempt to make this read operation non-blocking.

This dd(1) operand is a non-standard extension of GNU dd; its use is normally not recommended because it may leave your terminal in non-blocking state after exiting of the emulator.

I8080ASH_ASSUME_NONBLOCK_STDIN

Normally the emulator will run a simple Perl script on startup to make stdin non-blocking if necessary. If your stdin is already in non-blocking state, set this to a non-empty string to tell the emulator to skip this step.

I8080ASH_USE_STTY_MIN_TIME

Set this to a non-empty string to try to make the terminal on stdin non-blocking by running stty min 0 time 0. Ignored if stdin is not a terminal.

This may be necessary on Solaris, as the usual method for making a file descriptor non-blocking may be ineffective for terminals, on this operating system.

I8080ASH_PRINT_REGISTERS_ON_HALT

Set this to a non-empty string to make the emulator printing register values to stderr on execution of HLT instruction, before exiting.

Examples

sh i8080.ash c_bios.bin
cat c_bios.bin > /dev/fb0
sh i8080-rw.ash /dev/fb0
A=0 B=0 C=255 D=77 E=255 H=238 L=212 SP=61245 PC=64277 FLAGS=84 sh i8080.ash my-last-save

Transfer files into virtual disk image

This emulator did not implement the file import support as available in Toledo‘s emulator. You will have to use Toledo’s emulator for this task, if needed.

You may follow the instructions on https://www.ioccc.org/2006/toledo2/index.html or https://web.archive.org/web/20120112040347/http://nanochess.110mb.com/emulator.html to transfer files into your virtual disk images.

History

The initial work of this project was began in 2021, as improvements to the i8080 emulater in bash that written by NASZVADI Peter. The improvements I made include bug fixes for existing instructions, implementation of new instructions, and disk I/O support, to enable the emulator to correctly run CP/M, as well as Zork I for CP/M; other added features include significantly faster loading of user-specified memory image file, advanced Ctrl-C handling including memory dump support, ability to save and restore of emulation state, and an alternative variant for direct memory file access (for playing with /dev/fb0).

I was excited to demonstrate this version at the time; the result is this video on YouTube, Zork, CP/M running on BASH, with /dev/fb0 as memory.

However, there a serious issue with the original program by NASZVADI Peter; it did not came with a license, to enable 3rd-party distribution permission for the program! Unfortunately the original author refused to license it, so sadly the program remains proprietary to this day.

The solution? Rewrite the entire emulation logic from scratch! This move also provided a bonus that I was able to target the program to Almquist shell instead of bash; this creates a significant performance advantage over the old proprietary implementation, if an efficient implementation of Almquist shell is used, such as FreeBSD ash or dash 0.5.5.1.

License

Source files i8080.ash and i8080-rw.ash are distributed under the Mozilla Public License, version 2.0; a copy of this license is provided as COPYING file.

Binary files c_basic.bin and c_bios.bin are distributed under Creative Commons Attribution-ShareAlike 4.0 International license.