Paolo Amoroso's Journal

Tech projects, hobby programming, and geeky thoughts of Paolo Amoroso

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:

A>CLS

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

                    ret


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

                    end

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


                    cseg

                    mov     cl, WRITESTR
                    lea     dx, clshome
                    int     224

                    mov     cl, TERMCPM
                    int     224


                    dseg

                    org     100h

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

                    end

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 @amoroso@fosstodon.org

I fulfilled the requirements of the Bring Back Blogging challenge, i.e. posting at least three times over January of 2023. I published 8 posts with not much effort as this is more or less my average output. This is my first blogging challenge and I'm glad I took it as it set a realistic goal, not the usual death march.

#blogging

Discuss... Email | Reply @amoroso@fosstodon.org

After encountering Medley Interlisp I set out to learn the system, as I'd like to contribute to the project and use Medley Interlisp as my primary development environment.

Along with reading the documentation and playing with the system, I started a programming project.

I wanted to create something small that carries out a limited but useful task. My goal was to familiarize with the Medley Interlisp development environment, tools, and process through developing, optimizing, documenting, and sharing an Interlisp program.

I hoped to build a prototype with basic functionality I could finish quickly to have something to play with and extend. Blame instant gratification, and Lisp's productivity.

So I wrote a program I called Stringscope as a nod to the Masterscope program analysis tool of Interlisp.

The program

Stringscope is a tool to display a list of the text strings contained in a binary file, i.e. the sequences of printable characters longer than a minimum threshold of 4 characters. The program is similar to the Unix tool strings.

This is the output window of Stringscope:

Stringscope, an Interlisp program to list the text strings in a binary file.

The above screenshot is a crop of the full Medley Interlisp desktop:

Medley Interlisp desktop with the output and source windows of Stringscope, a program for listing the text strings in a binary file.

The Stringscope window shows the output of feeding into the program a word processor document as input. At the right of Stringscope is the TEdit rich text editor with the same document loaded. TEdit writes binary files that contain text and formatting commands, some of which are seen at the bottom of Stringscope window's. The largest window on the desktop shows the source code of Stringscope.

The scroll bar along the left edge of Stringscope's window is a small win I'm proud of.

The Medley Interlisp windowing environment doesn't automatically repaint program-created windows. So I had to figure out how set up Stringscope's window to repaint its content and make it scrollable. I managed to find the right code snippet in the Interlisp Reference Manual and repurposed it.

Usage

Stringscope first needs to be loaded by evaluating this Lisp expression, which assumes the file is in the current directory:

(LOAD 'STRINGSCOPE)

Next, the program is launched by evaluating:

(STRINGSCOPE FILENAME MIN.LEN)

where FILENAME is a file name and MIN.LEN the optional minimum length text strings must have. The default is 4 characters but is user-configurable by changing the global variable SSCOPE.MIN.LEN.

The function STRINGSCOPE opens the input file and feeds the resulting stream into the EXTRACT.STRINGS function, which runs a state machine that recognizes strings and adds them to the output. After receiving the returned list of strings, STRINGSCOPE prompts the user to create a window and sets it up to display the output and respond to repaint and scroll events.

Development

I developed Stringscope on my Chromebox with Interlisp Online, the cloud version of Medley Interlisp accessible from a browser via the noVNC VNC client.

Coding with the SEdit structure editor was smooth and highly productive.

As an image-based environment, in Medley Interlisp the code in memory may be saved to permanent storage by dumping the full memory image. But sources are usually saved to external files by the File Manager that's conceptually similar to the Unix tool Make. The File Manager is a collection of tools to notice, keep track of, and write to files the changes to a Lisp system under development.

Optimization

So far I ran Stringscope on small inputs but I eventually want to process larger files which may require optimizing the code with Spy, the main profiling tool of Medley Interlisp.

To get a feel of Spy I instrumented STRINGSCOPE, soon realizing the profiler collects a lot of unnecessary data related to window and system functions that have little influence on the overall running time. So I'll focus the analysis on EXTRACT.STRINGS which performs the I/O, manipulates the data, and does most of the processing.

Documentation

A lot of the digital documentation that ships with Medley Interlisp and user-contributed software was written with TEdit, the system's versatile rich text editor.

I'd like to use it to write the documentation of Stringscope but TEdit is not fully usable yet. The arrow keys don't work, a showstopper for non trivial text editing. The restoration and modernization of Medley Interlisp is under way and the issue will eventually be fixed, but I'll have to defer natively documenting Stringscope until then.

In the meantime these notes on my blog will have to do.

Sharing

Another major goal of Stringscope is to share my work and get feedback from experienced Interlisp developers.

Interlisp code is stored in “symbolic files”, Medley Interlisp jargon for source files. However, symbolic files are databases rather than traditional source files and they aren't usually edited directly. Instead, code is edited in memory with SEdit and the File Manager takes care of writing and updating symbolic files when the code is modified.

Although symbolic files are text files, exporting and publishing them involves some preparation and adaptation.

First, with Online Interlisp the files need to be downloaded from the cloud. Next, they may need some cleaning.

Symbolic files contain control codes for syntax highlighting and prettyprinting to render different text sizes and attributes such as bold. See for example the Stringscope code in the above screenshot of the desktop.

This is an effective way of presenting code in the environment. The downside is many Lisp symbols are wrapped in sequences of control codes that encode the formatting, which look like spurious characters in ASCII viewers and editors. Moreover, some Interlisp symbols, such as the left arrow , have the same ASCII code of the underscore character _.

I manually downloaded Stringscope's symbolic file with the noVNC file manager of Online Interlisp, pasted it into a text editor to strip the control codes, pasted the cleaned up code into a GitHub gist for publication, and replaced _ with .

The result is acceptable. But this quick solution is not adequate in the long term as it doesn't scale, and the code can't be directly loaded into Medley Interlisp.

I'll think about how to automate the download and sharing of symbolic files, likely via GitHub. A repo is handy also for hosting PDF files obtained by printing symbolic files to PostScript files in Medley Interlisp and converting to PDF. The PostScript output preserves the text formatting and is easier to read.

Further development

Stringscope is an ongoing project and there's still work to do starting from what is missing, such as profiling and documenting. Another step is to compile the program, as I ran it interpreted so far, making sure the latest compiled binary is loaded.

I'd also like to extend Stringscope with new features such as user interface controls and options for sorting the output, filtering it by string length, and rescanning the input with different minimum string lengths. And it shouldn't be too difficult to call Stringscope from the FileBrowser when a file is selected.

Finally, I want to allow other Lisp programs and functions to call Stringscope to receive the raw output for further processing. In Medley Interlisp, pretty much every piece of code is a building block other code may access and use, so I want Stringscope to contribute too.

Above all, I want Stringscope's evolution to help improve my proficiency with Medley Interlisp.

#lisp

Discuss... Email | Reply @amoroso@fosstodon.org

Medley Interlisp is the cover story of issue 70 of 8bitnews. I brought the historical Lisp environment to the attention of the 8bitnews editors, who published a story that also shares the post on my encounter with Medley Interlisp. Thanks Jan and Bastian!

8bitnews is my favorite retrocomputing newsletter, an interesting and engaging resource I always look forward to reading.

#lisp #retrocomputing

Discuss... Email | Reply @amoroso@fosstodon.org

Although I used several Lisp systems over a couple of decades, I never tried structure editing.

The chance finally came when I encountered Medley Interlisp, the Lisp system that pioneered structure editing. In particular I use SEdit which is the most advanced and user-friendly Interlisp structure editor.

I really like structure editing. It feels easier than I expected, natural, and productive. Plus it's a lot of fun.

The Medley Interlisp project is rehosting and modernizing the system to run on contemporary operating systems and computers but there are still a few rough edges, such as missing or broken keystrokes. Most notably the arrow keys don't work. I assumed this would severely limit coding with SEdit, but it turns out the tool can still be used productively and with very little friction.

Despite the issue, mouse operation in SEdit may be faster than the equivalent keystrokes of traditional text editors.

For example, once the cursor is at the destination, selecting and moving a complex list structure can be done with a single mouse click while holding down the Shift and Ctrl keys. Text editors typically require delimiting the code block to move, which takes a few keystrokes to go to and mark the end points, and executing the move command with an additional keystroke or more.

Where structure editing shines is with rearranging code. The structure-aware commands to select expressions and lists make it fast to copy, move, adjust the nesting level of, or delete large code blocks with a few mouse clicks or keystrokes.

Text editors allow inserting characters almost anywhere, while SEdit enforces the Lisp syntax and lets me type code only where allowed. But thinking in terms of structures instead of character sequences is less constraining that I thought. I enter Lisp expressions in a fill-in-the-blanks kind of way, in which the blanks are the spots where the syntax allows something. Sometimes it helps to type the code in a top-down way, from the outer list structures to the inner ones.

After relatively little practice with SEdit the awareness of structure editing is fading away, thus letting me focus on the code. It's now second nature and I no longer pay attention to how to perform editing tasks, as my muscle and action memory kicks in.

I had a similar early experience with Lisp's parentheses. They “disappeared” very soon and never were a source of friction.

#lisp

Discuss... Email | Reply @amoroso@fosstodon.org

To fight the threat of ChatGPT and other competing machine learning technologies based on GPT-3, Google is doubling down on AI. The first announcements under the new stategy are expected at Google I/O 2023.

I may be old school, but I'm not looking forward to these upcoming Google products and technologies.

As a user, my experience with the Google Assistant has been unimpressive. The features I tried work half of the times and waste my time in failed attempts at getting understood. When such localized features are rolled out at all to my country years later, that is.

So I'm not excited at the prospect of, say, an AI-enhanced Google Search experience.

I don't want a nice, perfectly idiomatic conversation with a chatbot that ends up recommending the usual shallow, keyword-stuffed, SEO-optimized crap of top search results. Maybe created by some ChatGPT-powered bot.

I want products and features created with traditional, boring software and hardware technologies. Something that works all of the times and consistently makes a difference in my productivity and ability to carry out tasks.

Here are a few Google product features that would make me jump with joy:

  • Markdown in Gmail
  • native Android support for full app data syncronization in the cloud, so seamless and compelling developers just can't say no
  • enforcing the requirement that all new Android apps must work also on chromeOS
  • true, substantial (at least 8X) optical zoom in Pixel phones
  • native Docker support in chromeOS
  • full Android app mirroring on chromeOS, not just messaging

Between Google chasing the latest hype, and advanced users always getting a back seat in product decisions, something tells me I'm not going to see any of these features anytime soon.

#Google

Discuss... Email | Reply @amoroso@fosstodon.org

The post on my encounter with Medley Interlisp ended up on the front page of Hacker News, receiving over 34K views and a lot of attention.

Larry Masinter, one of the original Medley Interlisp designers and current maintainers, invited me to join the project. I'm really honored and happy to have accepted, as I'm meaning to explore Medley Interlisp and use it as my main development environment. Also, I hope to give something back to this incredible retrocomputing project.

My first pull request was merged. It's a trivial change that adds a new section, written by another maintainer, to a page of the project website. But I'm pleased as it helped me familiarize with the development process, the code base, and the toolchain.

I'll initially focus on documentation and outreach, a byproduct of my learning journey. In the long term I may venture into contributing some fixes or additional Lisp code.

#lisp #retrocomputing

Discuss... Email | Reply @amoroso@fosstodon.org

When I researched a printer for my first Chromebox in 2015, going with a Brother HL-2340DW seemed like a no brainer.

It was one of the few affordable, wireless laser units with support for Google Cloud Print, then the only way of printing from chromeOS. Print quality is okay. But I never liked the HL-2340DW much as it's slow, and it often went into a deep sleep mode from which it was difficult to wake up.

When Google discontinued Cloud Print in 2020 I could still use the HL-2340DW from my new Chromebox via the IPP protocol, but the unit would often ignore print jobs. When printing from the Chromebox the HL-2340DW would acknowledge receiving the data, then just ignore the jobs and return to the ready state. No troubleshooting or combination of restarting chromeOS, the Chromebox, or the printer would help.

One of the times, exasperated, I initiated printing the Google Drive files I wanted from my Pixel 4 XL Android phone instead of the Chromebox. The printer worked flawlessly, and it has been from Android since then.

#chromeOS #Android

Discuss... Email | Reply @amoroso@fosstodon.org

My first Medley Interlisp blog post was shared on Hacker News, got over a hundred upvotes, and ended up on the front page, where it still is a day later after climbing up to number 5. So far my post received over 24K views, and counting.

I'm really glad Medley Interlisp is gaining some very well deserved attention.

#blogging #lisp

Discuss... Email | Reply @amoroso@fosstodon.org

Imagine someone let you into an alien spaceship they landed in your backyard, sat you at the controls, and encouraged you to fly the ship. This is the opportunity Medley Interlisp offers.

The project

Medley Interlisp is a project aiming to restore the Interlisp-D software environment of the Lisp Machines Xerox produced since the early 1980s, and rehost it on modern operating systems and computers. It's unique in the retrocomputing space in that many of the original designers and implementors of major parts of the system are participating in the effort.

The project started slightly over three years ago and is little known, so I stumbled upon it by chance. I was immediately drawn to Medley Interlisp for two reasons.

My experience with Lisp

First, I have a soft spot for Lisp. Since the early 1990s, for a couple of decades I extensively used several Lisp dialects and systems such as Scheme, Common Lisp, and Emacs Lisp.

I read a lot about Lisp Machines and their lost wonders but never got a chance to use one.

Although I always wanted to try such a system, hardware solutions are impractical and there are only a handful of Lisp Machine emulators, usually limited or difficult to set up. So the second reason Medley Interlisp caught my attention is, unlike similar efforts, it offers a complete environment that's easy to install and run. It can even run in the cloud and be accessed in a browser, here it is on my Chromebox:

Medley Interlisp running in a browser on chromeOS.

Why Medley Interlisp is different

The Medley Interlisp project is significant because it provides access to the full Interlisp-D software system. Working with a Lisp Machine environment feels like an encounter with an advanced civilization, so the spaceship metaphor is fitting.

A number of features make the image-based environments of Lisp Machines unique and still largely unparalleled by traditional file-based development environments and tools, where code is stored in source files and the environments are separate from the systems being built.

In an image-based environment, the developer builds programs by directly adapting and extending the running image of a system that consists of system software and development tools. The programs under development and the tools they're built with share the same space.

Everything is an API. Pretty much everything — system services, functions, user code, data structures, libraries, tools, GUI components and graphics, files, and resources — can access, inspect, call, and modify everything else. The environment provides a myriad of such building blocks that can be easily and quickly combined in countless ways to create more complex systems.

All these features transform Medley Interlisp into a productive, controlled creative chaos that encourages and supports prototyping and exploration.

The challenges

Medley Interlisp has some key strenghts, such as a rich environment and the ability to run in a browser. But the restoration and rehosting work is still under way, which makes using the system even more challenging.

The learning curve of such a complex system is steep, almost vertical.

This is less of an issue than it seems as I overcome these hurdles by diving deep into the documentation. I read everything I come across and at first not much makes sense. Eventually, my brain processes in the background all the information and the pieces start to fall into place.

Medley Interlisp comes with a dozen thousand pages worth of manuals, books, and academic papers, not to mention Lisp's built-in documentation and introspection facilities. I hope this knowledge will eventually help me contribute to the project in some way.

Also, due to the many layers of modern software the system now runs on, some of the original keybindings are broken or not properly mapped.

For example, pressing the arrow keys has no effect and doesn't move the text cursor. The keys are important for controlling system tools such as code and text editors. But, for the time being, there are good mouse-based alternatives that don't introduce too much friction when coding.

How I'll use Medley Interlisp

Despite some issues, my interest in Medley Interlisp goes beyond studying a significant software artifact of the history of computing. This decades old environment still has great practical value.

I'd like to use Medley Interlisp as my primary development environment for exploring problem domains, prototyping, and learning computer science. The problem understanding and design insights gained by experimenting with Medley Interlisp can be transferred to the projects I choose to implement with modern programming languages and tools.

The performance of the rehosted Medley Interlisp is pretty good. On my Chromebox it even runs faster in the browser than in the Crostini Linux container.

And I love the timeless, clean design of the black and white Medley Interlisp GUI, a style that evokes the elegance of printed paper. Only some pixelation gives away the historical roots of Medley Interlisp in an era predating the wide support for anti-aliasing.

As a hobby programmer I get to decide what tools to use and what projects to work on. I highly enjoy this complete creative freedom. The freedom to play with the tools I love, no matter how old or weird.

#lisp #retrocomputing

Discuss... Email | Reply @amoroso@fosstodon.org

Enter your email to subscribe to updates.