Paolo Amoroso's Journal


Sometimes experimenting with the Z80-MBC2 and V20-MBC homebrew CP/M computers leaves the screen garbled or in an unusable state, usually because some program doesn't correctly handle the terminal. The Minicom terminal emulator I use for CP/M sessions has a command for clearing the screen but it may not be enough.

Since a native CP/M solution is more effective I wrote two short utilities in Assembly for properly clearing and initializing the screen.

These transient programs share the same name, CLS. One runs under CP/M-80 on the Z80-MBC2 with a Z80 processor, the other under CP/M-86 on the V20-MBC with a Nec V20 in 8088 mode. Both assume an ANSI/VT100 terminal and are launched by executing CLS at the command prompt:


The programs work the same way not just due to the similarity of CP/M's design across different architectures, but also because they are variations of a hello world demo that prints a text string to the console.

After defining constants for the CP/M system functions and resources they access, the CLS programs call the write string BDOS function to output a string of ANSI escape codes for clearing the screen and moving the cursor to the home position. The definition of the string ends both programs.

CLS for CP/M-80

The CLS program for CP/M-80 is written in Intel 8080 Assembly:

; Clear the screen.
; Runs on CP/M-80 with an ANSI/VT100 terminal.

TPA                 equ     100h
BDOS                equ     05h
WRITESTR            equ     09h             ; Write string

                    org     TPA

                    mvi     c, WRITESTR
                    lxi     d, clshome
                    call    BDOS


; ANSI escapes:
;   clear screen      : ESC [ 2 J
;   go to screen home : ESC [ H
clshome:            db      1bh, '[2J', 1bh, '[H$'


For a short program like this that doesn't need a large stack a ret instruction is adequate to return control to CP/M.

I assembled the program with the asm80 assembler of Suite8080, my suite of 8080 Assembly cross-development tools in Python, and transferred the CLS executable to the Z80-MBC2 over the serial line.

CLS for CP/M-86

CLS for CP/M-86 is written in Intel 8086 Assembly. Aside from the different instruction set and the segmentation directives, this version calls the 00h BDOS function of int 224 to return control as CP/M-86 requires:

; Clear the screen.
; Runs on CP/M-86 with an ANSI/VT100 terminal.

WRITESTR            equ     09h             ; BDOS function write string
TERMCPM             equ     00h             ; BDOS function terminate program


                    mov     cl, WRITESTR
                    lea     dx, clshome
                    int     224

                    mov     cl, TERMCPM
                    int     224


                    org     100h

; ANSI escapes:
;    clear screen      : ESC [ 2 J
;    go to screen home : ESC [ H
clshome             db      1bh, '[2J', 1bh, '[H$'


I transferred the Assembly source to the V20-MBC over the serial line and assembled it with the hosted ASM86 assembler that comes with CP/M-86.

#Assembly #z80mbc2 #v20mbc

Discuss... Email | Reply

Beagle Term is a terminal emulator Chrome packaged app for controlling serial USB devices.

I checked it out with the Z80-MBC2 and the V20-MBC homebrew computers on my Chromebox and the app works well, with good VT100 emulation. A major downside is it doesn't support XMODEM or other file transfer protocols. And Google deprecated Chrome apps, so this one will eventually be discontinued.

When plugging a serial device into a USB port, chromeOS prompts to connect to the device from the Crostini Linux or the Android container. But Beagle Term runs in Chrome, so the selection isn't necessary and the notification may be dismissed.

Launching the app opens a connection configuration dialog prefilled with the default communication parameters, which are fine for the homebrew computers.

As I said VT100 emulation is pretty good. For example, here is the CatChum Pacman clone running under CP/M Plus on the Z80-MBC2:

CatChum Pcaman clone under CP/M Plus on the Z80-MBC2 homebrew computer.

And this is what WordStar 4 looks like under CP/M-86 on the V20-MBC:

WordStar under CP/M-86 on the V20-MBC homebrew computer.

Good VT100 support shouldn't be taken for granted in terminal emulators as it may be missing or broken such as in CuteCom or Serial USB Terminal.

#z80mbc2 #v20mbc #chromeOS

Discuss... Email | Reply

I'm always looking for terminal emulators and communication programs for controlling the Z80-MBC2 and V20-MBC, hoping they provide useful features Minicom misses.

That's why when stumbling upon CuteCom I eagerly checked it out. CuteCom is a graphical serial terminal program for Linux with a clean and simple user interface.

I tried it in Crostini Linux on my Chromebox connected to the Z80-MBC2 and the V20-MBC. The layout of CuteCom's window reminds me of the Serial USB Terminal app for Android which, unlike Minicom's single input and output area, has an input field separate from the output area.

The basic features of CuteCom are okay, but the program has major limitations when used with my homebrew computers. The main one is the program does no terminal emulation, doesn't support the escape codes for terminal control, and doesn't even properly align the output of a simple program like DIR. This screenshot of a V20-MBC CP/M-86 session shows the issue:

CuteCom terminal connected to a V20-MBC homebrew CP/M-86 computer.

I checked out CuteCom also with the Z80-MBC2 and tried to upload a file with XMODEM to a CP/M Plus session. However, an error informed CuteCom was unable to start the Linux program sz. There were no other clues and CuteCom has no documentation, so I have no idea what may be wrong. sz seems correctly set up under Crostini.

Given these issues, I can't unfortunately use CuteCom with the Z80-MBC2 and the V20-MBC.

The program is not a full terminal emulator to run programs that send terminal control codes to format the output. Instead, it's designed for the different use case of accessing electronic boards, embedded systems, and other devices via a serial connection, which typically produce line-oriented output.

#z80mbc2 #v20mbc

Discuss... Email | Reply

I assumed in Turbo Pascal for CP/M, when printing to a terminal, writeln wraps lines longer than the screen width. A quick test under CP/M-86 on the V20-MBC proved such lines are truncated instead. In hindsight it makes sense, as there's limited output state on a terminal system with no frame buffer.

#v20mbc #retrocomputing #development

Discuss... Email | Reply

To code on the Z80-MBC2 and V20-MBC homebrew computers I often transfer text files to and from their CP/M environments.

In one direction I send files from Crostini Linux by dumping them to CP/M, where PIP saves the text to CP/M files. In the opposite direction I run PIP on CP/M to print the files to the screen, where Minicom captures the text and saves it to files on Crostini.

CP/M and Unix have different line break and end of file encodings. In addition, the transfer process may introduce unwanted text. That's why the text files exchanged between the systems need some conversion, to automate which I wrote two short Bash scripts.

The first script, unix2cpm, converts line breaks and the end of file marker in the input to the CP/M encoding and prints the result to stdout. If the optional file name argument isn't supplied the script reads from stdin with a technique I researched. This is the script:

#!/usr/bin/env bash

# Convert line breaks and end of file from Unix to CP/M.
# Usage:
#   unix2cpm [filename]
# Reads from stdin if the optional argument is missing.


cat "$input_file" | unix2dos
echo -e -n '\x1a'

The script calls unix2dos distributed with the dos2unix / unix2dos tools. unix2dos converts line breaks from Unix to MS-DOS, which borrows the encoding from CP/M. unix2cpm needs only to append with echo the ^Z end of file control character.

Once converted, the file is ready to be dumped from Linux to CP/M.

I initiate file transfers in the oppostite direction by executing the Minicom command to capture the terminal output to a file, Ctrl-A L (Capture on/off). Then, at the CP/M prompt, I execute a command like this to print a file to the console:

A>a:pip con:=filename.txt

When printing ends and the A> prompt reappears, I turn off output capture in Minicom to close the capture file. The captured output contains the PIP command in the first line, then the text of the file, and finally the A> prompt in the last line.

To remove the unwanted first and last line I wrote the second script, skipfl (skip first and last). Again, the script reads from stdin if the optional file name isn't supplied and writes to stdout. The code is:

#!/usr/bin/env bash

# Skip the first and last file of the argument file
# Usage:
#   skipfl [filename]
# Reads from stdin if the optional argument is missing.


cat "$input_file" | sed '1d' | sed '$d'

The script calls sed to delete the first and last line with the d command.

No further processing of the captured CP/M output file is necessary as Minicom takes care of inserting the proper line break and end of file encodings.

#z80mbc2 #v20mbc #linux #retrocomputing

Discuss... Email | Reply

Turbo Pascal 3.0 for CP/M has a display issue I noticed on the Z80-MBC2 and V20-MBC homebrew computers. When using the development environment, text in the terminal remained stuck with boldface turned on.

It was enough to launch Turbo Pascal and execute any command (e.g. compiler Options), or exit Turbo Pascal, to turn on boldface and leave it stuck in the IDE, in CCP, and when running other programs. Everything went bold such as code in source files edited in Turbo Pascal, CCP command lines, and the output of transient programs.

The issue occurred under CP/M 3.0 on the Z80-MBC2 and CP/M-86 1.1 on the V20-MBC, both accessed from the Minicom terminal emulator under Crostini Linux on my Chromebox.

I tried ANSI and VT102 emulation in Minicom and run the Turbo Pascal configuration utility TINST to set the terminal to ANSI, but the issue persisted. The only workaround was to resize the terminal window, which reinitializes the display.

I posted to comp.os.cpm for help and learnt Borland left the terminal reset string blank in the ANSI entry, which thus doesn't reset text attributes.

The fix was simple. I run TINST, selected the ANSI terminal, and edited the definition to insert the following reset string via the option Send a reset string to the terminal (the corresponding escape code strings and descriptions are below the hex values):

$1b $63    $1b  $5b $32 $4a

ESC c      ESC  [   2   J
Reset      Clear screen

ESC c is not enough as it only resets the terminal but doesn't clear the screen. With the new string the text attributes are now properly handled and the terminal is no longer stuck in boldface after using Turbo Pascal.

#z80mbc2 #v20mbc #retrocomputing

Discuss... Email | Reply

The option 4: Autoboot-80 of the V20-MBC boot menu switches the Nec V20 to Intel 8080 mode and loads version 1.4 of the IMSAI 8K BASIC interpreter. In this session I typed in and run a short BASIC program to print the ASCII character set:

IMSAI BASIC on the V20-MBC homebrew computer.

The code is:

10 FOR I=32 TO 127

Despite the brevity, entering the code I bumped into some unexpected errors and behavior. It's been almost four decades since I used a resident BASIC on a microcomputer, and never with a terminal. No wonder interacting with IMSAI BASIC felt weird.

Reading the IMSAI BASIC manual and experimenting with the interpreter cleared the hurdles and let me make progress, though I'm not sure whether the issues may be related to the terminal settings. By the way, the commented Assembly source of the interpreter in the manual is an interesting reading.

Here are some notes on what I learned.

BASIC keywords, commands, and identifiers must be in all uppercase. Lowercase is supported only in strings assigned to variables, but printing string literals yelds uppercase text.

Pressing Backspace or Ctrl-H moves the cursor one character to the left and Del does nothing. The only ways of fixing typos or errors are deleting the whole line with Ctrl-U or entering it again.

When the environment gets messed up I execute the NEW command that clears the program and data, thus letting me start from scratch.

#v20mbc #retrocomputing

Discuss... Email | Reply

Turbo Pascal 3 for CP/M comes preinstalled with the Z80-MBC2 and V20-MBC homebrew computers. Checking out the development environment made me rediscover Turbo Pascal and realize its potential for programming these computers.

Although I owned Turbo Pascal for MS-DOS in the early 1990s, I didn't use it much. Between other languages later getting my attention and Borland losing its market leadership, I eventually forgot about Turbo Pascal. Now, with the development environment handy on the Z80-MBC2 and V20-MBC, I began checking out the Turbo Pascal CP/M version I had never played with.

Being familiar with the Turbo Pascal MS-DOS IDE, which features a nice text user interface with pull-down menus and dialogs, the CP/M version seemed spartan and primitive.

But I pressed ahead, tried the various commands, edited and compiled some code, and got familiar with the keystrokes and workflow. I soon felt at ease with Turbo Pascal for CP/M. The environment is still suprisingly usable and productive, allowing fast edit-compile-run cycles with short compilation times even on the 8-bit Z80-MBC2.

I now understand why Turbo Pascal made such a sensation at the time and revolutionized development tools.

To learn the Turbo Pascal environment and language I began reading the manual, as well as books about Turbo Pascal and Pascal. The more I used Turbo Pascal and read about it, the more I enjoyed it and wanted to learn and explore.

Next thing I knew, I was down a rabbit hole.

This experimentation and reading made me realize the potential of Turbo Pascal as an ideal tool for hobby projects with these homebrew computers.

Pascal is an easy to understand, readbale, and expressive language. Despite the age and design flaws, it allows to write fairly advanced code. Pascal makes practicality win over language purity.

Sitting at a sweet spot between ease of use, features, and power, Turbo Pascal is a perfect fit for CP/M as it consumes limited resources, generates moderatly small and fast executables, and can access all the features of the system. That's why it's a good environment for quickly developing small tools or programs for the Z80-MBC2 and V20-MBC.

#pascal #retrocomputing #z80mbc2 #v20mbc

Discuss... Email | Reply

On this blog I regularly share my retrocomputing experience and projects with the Z80-MBC2 and the V20-MBC homebrew computers. In addition, on my Mastodon account I often post screenshots, links, videos, and other short updates grouped under the #z80mbc2 and #v20mbc hashtags.

#z80mbc2 #v20mbc

Discuss... Email | Reply

CP/M-86 is a footnote to the history of the personal computer, which is part of why it's interesting.

The downside is the limited popularity the operating system enjoyed makes it difficult to discover online resources, particularly software. I face this issue when looking for software and tools for my V20-MBC homebrew computer, which can run CP/M-86 with the Intel 8088 of its Nec V20.

Therefore, I'm keeping track of the programs and software collections I run across online.

I include a list here, which I'll revise and expand with more entries. On the V20-MBC I tested only a small fraction of this software, so some programs designed for vendor-specific CP/M-86 versions or machines may not run on the device.

Repositories and collections

Old BBS archives, repositories, personal websites, and CD-ROM collections are good starting points. CP/M-86 software in executable form is usually in a section under general CP/M resources.

I found these repositories and websites:

Programs and utilities

Some applications are provided for download from their own websites or distribution archives:

Source code

Some software that works on CP/M-86 is distributed in source form with no prepackaged binaries. It's usually available at general CP/M repositories, in sections specific to the programming language or environment it was developed with such as Turbo Pascal or BASIC. This code may need some tweaks to run on CP/M-86.

For example, the Walnut Creek CP/M CD-ROM has a Turbo Pascal section.

CP/M-86 Miscellaneous Ports is a collection of C and Unix tools ported to CP/M-86, such as yacc.

#v20mbc #retrocomputing

Discuss... Email | Reply