cpm80
CP/M-80 2.2 emulator with Python API.
Based on the fast and flexible z80 emulator.
Running the 1982 CP/M game Ladder, loaded straight from the host directory:
Installing
$ pip install cpm80
Running and terminating
$ cpm80
62k CP/M vers 2.2
A>save 1 dump.dat
A>dir
A: DUMP DAT
A>exit
Enter exit or just hit Ctrl + C three
times to quit the emulator.
Exchanging files with the host
--mount <dir> puts a host directory on the next drive, and fresh
disks come with PIP, so files just copy.
$ ls
hello.txt
$ cpm80 --mount .
62k CP/M vers 2.2
A>dir b:
B: HELLO TXT
A>pip a:=b:hello.txt
A>save 1 b:dump.dat
A>exit
$ ls
DUMP.DAT hello.txt
--mount also takes a disk image file instead of a directory.
A single Ctrl + C re-reads a mounted
directory -- the usual CP/M way of telling the system the disk has
changed.
Running commands automatically
From the command line:
$ cpm80 dir 'save 1 a.dat' dir
Alternatively, we can use the API's StringKeyboard class to
feed arbitrary commands to the command processor, CCP, thus
replacing KeyboardDevice console readers used by default:
import cpm80
COMMANDS = (
'dir',
'save 1 a.dat',
'dir',
)
console_reader = cpm80.StringKeyboard(*COMMANDS)
m = cpm80.I8080CPMMachine(console_reader=console_reader)
m.run()
Output:
62k CP/M vers 2.2
A>dir
NO FILE
A>save 1 a.dat
A>dir
A: A DAT
A>
Getting output as a string
Similarly, we can replace DisplayDevice console writers used by
default with custom writers to do special work for the emulator's
output.
For example, one could use a StringDisplay writer to gather the
output into a string.
d = cpm80.StringDisplay()
m = cpm80.I8080CPMMachine(
console_reader=cpm80.StringKeyboard('dir'),
console_writer=d)
m.run()
print(d.string)
Making BDOS calls
BDOS calls can be performed on the machine object directly or by using convenience wrappers.
m = cpm80.I8080CPMMachine()
STR_ADDR = 0x100
m.set_memory_block(STR_ADDR, b'Hello $')
m.bdos_call(m.C_WRITESTR, de=STR_ADDR)
m.write_str('World!\n')
Working with files
Similarly, using BDOS wrappers one can manipulate files on disks.
drive = cpm80.DiskDrive()
m = cpm80.I8080CPMMachine(drives=[drive])
m.make_file('file.txt')
m.write_file(f'bin(100) is {bin(100)}\n'.encode())
m.close_file()
del m
# Then read and print the contents of the file using another machine.
m = cpm80.I8080CPMMachine(drives=[drive])
m.open_file('file.txt')
print(m.read_file())
m.close_file()
Metadata
Release files for cpm80 1.2.1
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| cpm80-1.2.1.tar.gz | 41.7 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| cpm80-1.2.1-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 75.5 kB
Release files / cpm80-1.2.1.tar.gz
| Download URL | cpm80-1.2.1.tar.gz |
|---|---|
| Size | 41.7 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
b77726a3f7fe077a85b3a0d50bf4c228159ec1eb2c641b0f67ebb0c956e074a4
|
|
BLAKE2b-256 checksum How to use checksums |
84007f7ac24a7783d8a222dfdfb4d3fb843b19bb561358347f869b0099b947c5
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 5, 2026.
Transparency logRelease files / cpm80-1.2.1-py3-none-any.whl
| Download URL | cpm80-1.2.1-py3-none-any.whl |
|---|---|
| Size | 33.8 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
7239d5ea29d0ed3a2913ff562579af2b8ee051f168489c26e1ef0df378cb9f47
|
|
BLAKE2b-256 checksum How to use checksums |
3ce3f2baa032ecc3f15c6301a9ac650fda8be502e3c15252515686eef1b55f1e
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 5, 2026.
Transparency log