<?xml version="1.0" encoding="UTF-8"?><rss version="2.0" xmlns:content="http://purl.org/rss/1.0/modules/content/">
  <channel>
    <title>z80mbc2 &amp;mdash; Paolo Amoroso&#39;s Journal</title>
    <link>https://journal.paoloamoroso.com/tag:z80mbc2</link>
    <description>Tech projects, hobby programming, and geeky thoughts of Paolo Amoroso</description>
    <pubDate>Wed, 29 Jul 2026 13:01:26 +0000</pubDate>
    <image>
      <url>https://i.snap.as/68i8povn.jpg</url>
      <title>z80mbc2 &amp;mdash; Paolo Amoroso&#39;s Journal</title>
      <link>https://journal.paoloamoroso.com/tag:z80mbc2</link>
    </image>
    <item>
      <title>Two CP/M programs to clear the screen</title>
      <link>https://journal.paoloamoroso.com/two-cp-m-programs-to-clear-the-screen?pk_campaign=rss-feed</link>
      <description>&lt;![CDATA[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&#39;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.&#xA;&#xA;Since a native CP/M solution is more effective I wrote two short utilities in Assembly for properly clearing and initializing the screen. &#xA;&#xA;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:&#xA;&#xA;A  CLS&#xA;&#xA;The programs work the same way not just due to the similarity of CP/M&#39;s design across different architectures, but also because they are variations of a hello world demo that prints a text string to the console.&#xA;&#xA;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.&#xA;&#xA;CLS for CP/M-80&#xA;&#xA;The CLS program for CP/M-80 is written in Intel 8080 Assembly:&#xA;&#xA;; Clear the screen.&#xA;;&#xA;; Runs on CP/M-80 with an ANSI/VT100 terminal.&#xA;&#xA;TPA                 equ     100h&#xA;BDOS                equ     05h&#xA;WRITESTR            equ     09h             ; Write string&#xA;&#xA;                    org     TPA&#xA;&#xA;                    mvi     c, WRITESTR&#xA;                    lxi     d, clshome&#xA;                    call    BDOS&#xA;&#xA;                    ret&#xA;&#xA;; ANSI escapes:&#xA;;   clear screen      : ESC [ 2 J&#xA;;   go to screen home : ESC [ H&#xA;clshome:            db      1bh, &#39;[2J&#39;, 1bh, &#39;[H$&#39;&#xA;&#xA;                    end&#xA;&#xA;For a short program like this that doesn&#39;t need a large stack a ret instruction is adequate to return control to CP/M.&#xA;&#xA;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.&#xA;&#xA;CLS for CP/M-86&#xA;&#xA;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:&#xA;&#xA;; Clear the screen.&#xA;;&#xA;; Runs on CP/M-86 with an ANSI/VT100 terminal.&#xA;&#xA;WRITESTR            equ     09h             ; BDOS function write string&#xA;TERMCPM             equ     00h             ; BDOS function terminate program&#xA;&#xA;                    cseg&#xA;&#xA;                    mov     cl, WRITESTR&#xA;                    lea     dx, clshome&#xA;                    int     224&#xA;&#xA;                    mov     cl, TERMCPM&#xA;                    int     224&#xA;&#xA;                    dseg&#xA;&#xA;                    org     100h&#xA;&#xA;; ANSI escapes:&#xA;;    clear screen      : ESC [ 2 J&#xA;;    go to screen home : ESC [ H&#xA;clshome             db      1bh, &#39;[2J&#39;, 1bh, &#39;[H$&#39;&#xA;&#xA;                    end&#xA;&#xA;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.&#xA;&#xA;#Assembly #z80mbc2 #v20mbc&#xA;&#xA;a href=&#34;https://remark.as/p/journal.paoloamoroso.com/two-cp-m-programs-to-clear-the-screen&#34;Discuss.../a&#xD;&#xA;Email | Reply @amoroso@oldbytes.space&#xD;&#xA;&#xD;&#xA;!--emailsub--]]&gt;</description>
      <content:encoded><![CDATA[<p>Sometimes experimenting with the <a href="https://journal.paoloamoroso.com/tag:z80mbc2">Z80-MBC2</a> and <a href="https://journal.paoloamoroso.com/tag:v20mbc">V20-MBC</a> homebrew CP/M computers leaves the screen garbled or in an unusable state, usually because some program doesn&#39;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.</p>

<p>Since a native CP/M solution is more effective I wrote two short <a href="https://gist.github.com/pamoroso/e06b75713719c12123ac71042e7cbd94">utilities in Assembly for properly clearing and initializing the screen</a>.</p>

<p>These transient programs share the same name, <code>CLS</code>. 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 <code>CLS</code> at the command prompt:</p>

<pre><code class="language-msdos">A&gt;CLS
</code></pre>

<p>The programs work the same way not just due to the similarity of CP/M&#39;s design across different architectures, but also because they are variations of a <a href="https://journal.paoloamoroso.com/a-hello-world-assembly-demo-running-on-the-z80-mbc2">hello world demo</a> that prints a text string to the console.</p>

<p>After defining constants for the CP/M system functions and resources they access, the <code>CLS</code> 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.</p>

<h2 id="cls-for-cp-m-80">CLS for CP/M-80</h2>

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

<pre><code class="language-asm">; 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, &#39;[2J&#39;, 1bh, &#39;[H$&#39;

                    end
</code></pre>

<p>For a short program like this that doesn&#39;t need a large stack a <code>ret</code> instruction is adequate to return control to CP/M.</p>

<p>I assembled the program with the <code>asm80</code> assembler of <a href="https://journal.paoloamoroso.com/tag:Suite8080">Suite8080</a>, my suite of 8080 Assembly cross-development tools in Python, and transferred the <code>CLS</code> executable to the Z80-MBC2 over the serial line.</p>

<h2 id="cls-for-cp-m-86">CLS for CP/M-86</h2>

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

<pre><code class="language-asm">; 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, &#39;[2J&#39;, 1bh, &#39;[H$&#39;

                    end
</code></pre>

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

<p><a href="https://journal.paoloamoroso.com/tag:Assembly" class="hashtag"><span>#</span><span class="p-category">Assembly</span></a> <a href="https://journal.paoloamoroso.com/tag:z80mbc2" class="hashtag"><span>#</span><span class="p-category">z80mbc2</span></a> <a href="https://journal.paoloamoroso.com/tag:v20mbc" class="hashtag"><span>#</span><span class="p-category">v20mbc</span></a></p>

<p><a href="https://remark.as/p/journal.paoloamoroso.com/two-cp-m-programs-to-clear-the-screen">Discuss...</a>
<a href="mailto:info@paoloamoroso.com?subject=Reply%20to%20Paolo%20Amoroso%27s%20Journal">Email</a> | Reply <a href="/@/amoroso@oldbytes.space" class="u-url mention">@<span>amoroso@oldbytes.space</span></a></p>


]]></content:encoded>
      <guid>https://journal.paoloamoroso.com/two-cp-m-programs-to-clear-the-screen</guid>
      <pubDate>Sun, 05 Feb 2023 13:03:14 +0000</pubDate>
    </item>
    <item>
      <title>Using Beagle Term with the Z80-MBC2 and V20-MBC</title>
      <link>https://journal.paoloamoroso.com/using-beagle-term-with-the-z80-mbc2-and-v20-mbc?pk_campaign=rss-feed</link>
      <description>&lt;![CDATA[Beagle Term is a terminal emulator Chrome packaged app for controlling serial USB devices.&#xA;&#xA;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&#39;t support XMODEM or other file transfer protocols. And Google deprecated Chrome apps, so this one will eventually be discontinued.&#xA;&#xA;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&#39;t necessary and the notification may be dismissed.&#xA;&#xA;Launching the app opens a connection configuration dialog prefilled with the default communication parameters, which are fine for the homebrew computers.&#xA;&#xA;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:&#xA;&#xA;CatChum Pcaman clone under CP/M Plus on the Z80-MBC2 homebrew computer.&#xA;&#xA;And this is what WordStar 4 looks like under CP/M-86 on the V20-MBC:&#xA;&#xA;WordStar under CP/M-86 on the V20-MBC homebrew computer.&#xA;&#xA;Good VT100 support shouldn&#39;t be taken for granted in terminal emulators as it may be missing or broken such as in CuteCom or Serial USB Terminal.&#xA;&#xA;#z80mbc2 #v20mbc #chromeOS&#xA;&#xA;a href=&#34;https://remark.as/p/journal.paoloamoroso.com/using-beagle-term-with-the-z80-mbc2-and-v20-mbc&#34;Discuss.../a&#xD;&#xA;Email | Reply @amoroso@oldbytes.space&#xD;&#xA;&#xD;&#xA;!--emailsub--]]&gt;</description>
      <content:encoded><![CDATA[<p><a href="https://chrome.google.com/webstore/detail/beagle-term/gkdofhllgfohlddimiiildbgoggdpoea">Beagle Term</a> is a terminal emulator Chrome packaged app for controlling serial USB devices.</p>

<p>I checked it out with the <a href="https://journal.paoloamoroso.com/tag:z80mbc2">Z80-MBC2</a> and the <a href="https://journal.paoloamoroso.com/tag:v20mbc">V20-MBC</a> homebrew computers on <a href="https://journal.paoloamoroso.com/why-i-use-a-chromebox">my Chromebox</a> and the app works well, with good VT100 emulation. A major downside is it doesn&#39;t support XMODEM or other file transfer protocols. And Google deprecated Chrome apps, so this one will eventually be discontinued.</p>

<p>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&#39;t necessary and the notification may be dismissed.</p>

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

<p>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:</p>

<p><a href="https://i.snap.as/353wwbTC.png"><img src="https://i.snap.as/353wwbTC.png" alt="CatChum Pcaman clone under CP/M Plus on the Z80-MBC2 homebrew computer."/></a></p>

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

<p><a href="https://i.snap.as/DKxSuID7.png"><img src="https://i.snap.as/DKxSuID7.png" alt="WordStar under CP/M-86 on the V20-MBC homebrew computer."/></a></p>

<p>Good VT100 support shouldn&#39;t be taken for granted in terminal emulators as it may be missing or broken such as in <a href="https://journal.paoloamoroso.com/checking-out-cutecom">CuteCom</a> or <a href="https://journal.paoloamoroso.com/controlling-the-z80-mbc2-from-android-on-chromeos">Serial USB Terminal</a>.</p>

<p><a href="https://journal.paoloamoroso.com/tag:z80mbc2" class="hashtag"><span>#</span><span class="p-category">z80mbc2</span></a> <a href="https://journal.paoloamoroso.com/tag:v20mbc" class="hashtag"><span>#</span><span class="p-category">v20mbc</span></a> <a href="https://journal.paoloamoroso.com/tag:chromeOS" class="hashtag"><span>#</span><span class="p-category">chromeOS</span></a></p>

<p><a href="https://remark.as/p/journal.paoloamoroso.com/using-beagle-term-with-the-z80-mbc2-and-v20-mbc">Discuss...</a>
<a href="mailto:info@paoloamoroso.com?subject=Reply%20to%20Paolo%20Amoroso%27s%20Journal">Email</a> | Reply <a href="/@/amoroso@oldbytes.space" class="u-url mention">@<span>amoroso@oldbytes.space</span></a></p>


]]></content:encoded>
      <guid>https://journal.paoloamoroso.com/using-beagle-term-with-the-z80-mbc2-and-v20-mbc</guid>
      <pubDate>Mon, 02 Jan 2023 13:21:17 +0000</pubDate>
    </item>
    <item>
      <title>Troubleshooting a Suite8080 assembler bug</title>
      <link>https://journal.paoloamoroso.com/troubleshooting-a-suite8080-assembler-bug?pk_campaign=rss-feed</link>
      <description>&lt;![CDATA[The iLoad feature of the Z80-MBC2 homebrew Z80 computer allows uploading binary code that runs on the bare metal.&#xA;&#xA;I thought it would be fun to try iLoad with some Intel 8080 code generated by the asm80 assembler of Suite8080, the suite of 8080 Assembly cross-development tools I&#39;m writing in Python. But the code crashed the Z80-MBC2, uncovering a major asm80 bug.&#xA;&#xA;It all started when, to practice the toolchain and process, I started with a Z80 Assembly demo that comes with the Z80-MBC2, which prints a message to the console and blinks one of the devices&#39;s LEDs. I assembled the program with the zasm Z80 and 8080 assembler, uploaded it via iLoad, and successfully ran it.&#xA;&#xA;Next, I ported the blinking LED demo from Z80 to 8080 code and assembled it with asm80. But when I ran the demo on the Z80-MBC2, it crashed the device. &#xA;&#xA;The baffling crash left me stuck for threee months, as I had no tools for debugging on the bare metal and there were only a few vague clues.&#xA;&#xA;I carefully studied the less than a hundred lines of code and they looked fine. To isolate the issue I cut the code in half, leaving the part that prints a message to the console, and transforming the blinking demo into this bare.asm hello world for the bare metal:&#xA;&#xA;OPCODEPORT     equ     01h&#xA;EXECWPORT      equ     00h&#xA;TXOPCODE       equ     01h&#xA;EOS             equ     00h&#xA;CR              equ     0dh&#xA;LF              equ     0ah&#xA;&#xA;                org     0h&#xA;&#xA;                jmp     start&#xA;&#xA;                ds      16&#xA;stack:&#xA;&#xA;start:          lxi     sp, start&#xA;                lxi     h, message&#xA;                call    puts&#xA;&#xA;                hlt&#xA;&#xA;message:        db      CR, LF, &#39;Greetings from the bare metal&#39;, CR, LF, EOS&#xA;&#xA;puts:           push    psw&#xA;                push    h&#xA;putsloop:      mov     a, m&#xA;                cpi     EOS&#xA;                jz      putsend&#xA;                call    putc&#xA;                inx     h&#xA;                jmp     putsloop&#xA;putsend:       pop     h&#xA;                pop     psw&#xA;                ret&#xA;&#xA;putc:           push    psw&#xA;                mvi     a, TXOPCODE&#xA;                out     OPCODEPORT&#xA;                pop     psw&#xA;                out     EXECWPORT&#xA;                ret&#xA;&#xA;                end&#xA;&#xA;The constants at the beginning define the addresses of the output ports, the opcode for sending a character over the serial line, and a couple of control characters. Next, the program sets up the stack and iterates over the output string to print every character.&#xA;&#xA;The simplified demo program still crashed the Z80-MBC2, forcing me back to the drawing board.&#xA;&#xA;Then I had an epiphany. What if the binary code asm80 generates is different from zasm&#39;s?&#xA;&#xA;I fired up the dis80 disassembler of Suite8080 and compared the output of the assemblers. Sure enough, the difference jumped at me: the destination addresses of all the branches after the label message are off by 5 bytes.&#xA;&#xA;The instructions branch to addresses 5 bytes lower, so the call to puts executes random string data that chrashes the device. The last correct address asm80 outputs is that of the label message. The address of the next one, puts, is wrong and leads to the crash.&#xA;&#xA;Indeed, the same demo code assembled with zasm ran fine on the Z80-MBC2 and printed the expected message. This confirmed my hunch.&#xA;&#xA;What now?&#xA;&#xA;The next step is to find the bug in the Python source of asm80, which I&#39;m developing with Replit. Although Replit provides a debugger, I won&#39;t use it. The tool is not well documented and I&#39;m not sure how it works. In addition the Replit debugger is best suited to code started from the run button. This is inconvenient for command line programs like the Python scripts of Suite8080.&#xA;&#xA;Therefore, I&#39;ll take the opportunity to use Python&#39;s native debugger pdb, which I always wanted to try in a real project. I played with pdb a bit and it looks easy to use, with all the commands and options handy.&#xA;&#xA;Let&#39;s see if pdb can help me pinpoint the bug in the Python code.&#xA;&#xA;#Suite8080 #z80mbc2 #Assembly #Python&#xA;&#xA;a href=&#34;https://remark.as/p/journal.paoloamoroso.com/troubleshooting-a-suite8080-assembler-bug&#34;Discuss.../a&#xD;&#xA;Email | Reply @amoroso@oldbytes.space&#xD;&#xA;&#xD;&#xA;!--emailsub--]]&gt;</description>
      <content:encoded><![CDATA[<p>The iLoad feature of the <a href="https://journal.paoloamoroso.com/tag:z80mbc2">Z80-MBC2</a> homebrew Z80 computer allows uploading binary code that runs on the bare metal.</p>

<p>I thought it would be fun to try iLoad with some Intel 8080 code generated by the <code>asm80</code> assembler of <a href="https://journal.paoloamoroso.com/tag:Suite8080">Suite8080</a>, the suite of 8080 Assembly cross-development tools I&#39;m writing in Python. But the code crashed the Z80-MBC2, uncovering a major <code>asm80</code> bug.</p>

<p>It all started when, to practice the toolchain and process, I started with a <a href="https://journal.paoloamoroso.com/testing-hex-file-upload-to-the-z80-mbc2">Z80 Assembly demo that comes with the Z80-MBC2</a>, which prints a message to the console and blinks one of the devices&#39;s LEDs. I assembled the program with the <a href="https://k1.spdns.de/Develop/Projects/zasm/Distributions">zasm</a> Z80 and 8080 assembler, uploaded it via iLoad, and successfully ran it.</p>

<p>Next, I ported the blinking LED demo from Z80 to 8080 code and assembled it with <code>asm80</code>. But when <a href="https://journal.paoloamoroso.com/first-attempt-at-porting-a-z80-led-blink-demo-to-8080">I ran the demo on the Z80-MBC2, it crashed the device</a>.</p>

<p>The baffling crash left me stuck for threee months, as I had no tools for debugging on the bare metal and there were only a few vague clues.</p>

<p>I carefully studied the less than a hundred lines of code and they looked fine. To isolate the issue I cut the code in half, leaving the part that prints a message to the console, and transforming the blinking demo into this <code>bare.asm</code> hello world for the bare metal:</p>

<pre><code class="language-asm">OPCODE_PORT     equ     01h
EXEC_WPORT      equ     00h
TX_OPCODE       equ     01h
EOS             equ     00h
CR              equ     0dh
LF              equ     0ah


                org     0h

                jmp     start

                ds      16
stack:


start:          lxi     sp, start
                lxi     h, message
                call    puts

                hlt


message:        db      CR, LF, &#39;Greetings from the bare metal&#39;, CR, LF, EOS


puts:           push    psw
                push    h
puts_loop:      mov     a, m
                cpi     EOS
                jz      puts_end
                call    putc
                inx     h
                jmp     puts_loop
puts_end:       pop     h
                pop     psw
                ret


putc:           push    psw
                mvi     a, TX_OPCODE
                out     OPCODE_PORT
                pop     psw
                out     EXEC_WPORT
                ret

                end
</code></pre>

<p>The constants at the beginning define the addresses of the output ports, the opcode for sending a character over the serial line, and a couple of control characters. Next, the program sets up the stack and iterates over the output string to print every character.</p>

<p>The simplified demo program still crashed the Z80-MBC2, forcing me back to the drawing board.</p>

<p>Then I had an epiphany. What if the binary code <code>asm80</code> generates is different from <code>zasm</code>&#39;s?</p>

<p>I fired up the <code>dis80</code> disassembler of Suite8080 and compared the output of the assemblers. Sure enough, the difference jumped at me: the destination addresses of all the branches after the label <code>message</code> are off by 5 bytes.</p>

<p>The instructions branch to addresses 5 bytes lower, so the call to <code>puts</code> executes random string data that chrashes the device. The last correct address <code>asm80</code> outputs is that of the label <code>message</code>. The address of the next one, <code>puts</code>, is wrong and leads to the crash.</p>

<p>Indeed, the same demo code assembled with <code>zasm</code> ran fine on the Z80-MBC2 and printed the expected message. This confirmed my hunch.</p>

<p>What now?</p>

<p>The next step is to find the bug in the Python source of <code>asm80</code>, which I&#39;m developing with <a href="https://replit.com">Replit</a>. Although Replit provides a debugger, I won&#39;t use it. The tool is not well documented and I&#39;m not sure how it works. In addition the Replit debugger is best suited to code started from the run button. This is inconvenient for command line programs like the Python scripts of Suite8080.</p>

<p>Therefore, I&#39;ll take the opportunity to use Python&#39;s native debugger <code>pdb</code>, which I always wanted to try in a real project. I played with <code>pdb</code> a bit and it looks easy to use, with all the commands and options handy.</p>

<p>Let&#39;s see if <code>pdb</code> can help me pinpoint the bug in the Python code.</p>

<p><a href="https://journal.paoloamoroso.com/tag:Suite8080" class="hashtag"><span>#</span><span class="p-category">Suite8080</span></a> <a href="https://journal.paoloamoroso.com/tag:z80mbc2" class="hashtag"><span>#</span><span class="p-category">z80mbc2</span></a> <a href="https://journal.paoloamoroso.com/tag:Assembly" class="hashtag"><span>#</span><span class="p-category">Assembly</span></a> <a href="https://journal.paoloamoroso.com/tag:Python" class="hashtag"><span>#</span><span class="p-category">Python</span></a></p>

<p><a href="https://remark.as/p/journal.paoloamoroso.com/troubleshooting-a-suite8080-assembler-bug">Discuss...</a>
<a href="mailto:info@paoloamoroso.com?subject=Reply%20to%20Paolo%20Amoroso%27s%20Journal">Email</a> | Reply <a href="/@/amoroso@oldbytes.space" class="u-url mention">@<span>amoroso@oldbytes.space</span></a></p>


]]></content:encoded>
      <guid>https://journal.paoloamoroso.com/troubleshooting-a-suite8080-assembler-bug</guid>
      <pubDate>Wed, 28 Dec 2022 12:42:50 +0000</pubDate>
    </item>
    <item>
      <title>Checking out CuteCom</title>
      <link>https://journal.paoloamoroso.com/checking-out-cutecom?pk_campaign=rss-feed</link>
      <description>&lt;![CDATA[I&#39;m always looking for terminal emulators and communication programs for controlling the Z80-MBC2 and V20-MBC, hoping they provide useful features Minicom misses.&#xA;&#xA;That&#39;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.&#xA;&#xA;I tried it in Crostini Linux on my Chromebox connected to the Z80-MBC2 and the V20-MBC. The layout of CuteCom&#39;s window reminds me of the Serial USB Terminal app for Android which, unlike Minicom&#39;s single input and output area, has an input field separate from the output area.&#xA;&#xA;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&#39;t support the escape codes for terminal control, and doesn&#39;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:&#xA;&#xA;CuteCom terminal connected to a V20-MBC homebrew CP/M-86 computer.&#xA;&#xA;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.&#xA;&#xA;Given these issues, I can&#39;t unfortunately use CuteCom with the Z80-MBC2 and the V20-MBC.&#xA;&#xA;The program is not a full terminal emulator to run programs that send terminal control codes to format the output. Instead, it&#39;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.&#xA;&#xA;#z80mbc2 #v20mbc&#xA;&#xA;a href=&#34;https://remark.as/p/journal.paoloamoroso.com/checking-out-cutecom&#34;Discuss.../a&#xD;&#xA;Email | Reply @amoroso@oldbytes.space&#xD;&#xA;&#xD;&#xA;!--emailsub--]]&gt;</description>
      <content:encoded><![CDATA[<p>I&#39;m always looking for terminal emulators and communication programs for controlling the <a href="https://journal.paoloamoroso.com/tag:z80mbc2">Z80-MBC2</a> and <a href="https://journal.paoloamoroso.com/tag:v20mbc">V20-MBC</a>, hoping they provide useful features Minicom misses.</p>

<p>That&#39;s why when stumbling upon <a href="https://gitlab.com/cutecom/cutecom">CuteCom</a> I eagerly checked it out. CuteCom is a graphical serial terminal program for Linux with a clean and simple user interface.</p>

<p>I tried it in Crostini Linux on my Chromebox connected to the Z80-MBC2 and the V20-MBC. The layout of CuteCom&#39;s window reminds me of the <a href="https://journal.paoloamoroso.com/controlling-the-z80-mbc2-from-android-on-chromeos">Serial USB Terminal</a> app for Android which, unlike Minicom&#39;s single input and output area, has an input field separate from the output area.</p>

<p>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&#39;t support the escape codes for terminal control, and doesn&#39;t even properly align the output of a simple program like <code>DIR</code>. This screenshot of a V20-MBC CP/M-86 session shows the issue:</p>

<p><a href="https://i.snap.as/pVSYm2E5.png"><img src="https://i.snap.as/pVSYm2E5.png" alt="CuteCom terminal connected to a V20-MBC homebrew CP/M-86 computer."/></a></p>

<p>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 <code>sz</code>. There were no other clues and CuteCom has no documentation, so I have no idea what may be wrong. <code>sz</code> seems correctly set up under Crostini.</p>

<p>Given these issues, I can&#39;t unfortunately use CuteCom with the Z80-MBC2 and the V20-MBC.</p>

<p>The program is not a full terminal emulator to run programs that send terminal control codes to format the output. Instead, it&#39;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.</p>

<p><a href="https://journal.paoloamoroso.com/tag:z80mbc2" class="hashtag"><span>#</span><span class="p-category">z80mbc2</span></a> <a href="https://journal.paoloamoroso.com/tag:v20mbc" class="hashtag"><span>#</span><span class="p-category">v20mbc</span></a></p>

<p><a href="https://remark.as/p/journal.paoloamoroso.com/checking-out-cutecom">Discuss...</a>
<a href="mailto:info@paoloamoroso.com?subject=Reply%20to%20Paolo%20Amoroso%27s%20Journal">Email</a> | Reply <a href="/@/amoroso@oldbytes.space" class="u-url mention">@<span>amoroso@oldbytes.space</span></a></p>


]]></content:encoded>
      <guid>https://journal.paoloamoroso.com/checking-out-cutecom</guid>
      <pubDate>Sun, 11 Dec 2022 16:33:30 +0000</pubDate>
    </item>
    <item>
      <title>Conversion scripts for CP/M file transfers</title>
      <link>https://journal.paoloamoroso.com/conversion-scripts-for-cp-m-file-transfers?pk_campaign=rss-feed</link>
      <description>&lt;![CDATA[To code on the Z80-MBC2 and V20-MBC homebrew computers I often transfer text files to and from their CP/M environments.&#xA;&#xA;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.&#xA;&#xA;CP/M and Unix have different line break and end of file encodings. In addition, the transfer process may introduce unwanted text. That&#39;s why the text files exchanged between the systems need some conversion, to automate which I wrote two short Bash scripts.&#xA;&#xA;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&#39;t supplied the script reads from stdin with a technique I researched. This is the script:&#xA;&#xA;!/usr/bin/env bash&#xA;&#xA;Convert line breaks and end of file from Unix to CP/M.&#xA;&#xA;Usage:&#xA;&#xA;unix2cpm [filename]&#xA;&#xA;Reads from stdin if the optional argument is missing.&#xA;&#xA;inputfile=&#34;${1:-/dev/stdin}&#34;&#xA;&#xA;cat &#34;$inputfile&#34; | unix2dos&#xA;echo -e -n &#39;\x1a&#39;&#xA;&#xA;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.&#xA;&#xA;Once converted, the file is ready to be dumped from Linux to CP/M.&#xA;&#xA;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:&#xA;&#xA;A  a:pip con:=filename.txt&#xA;&#xA;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.&#xA;&#xA;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&#39;t supplied and writes to stdout. The code is:&#xA;&#xA;!/usr/bin/env bash&#xA;&#xA;Skip the first and last file of the argument file&#xA;&#xA;Usage:&#xA;&#xA;skipfl [filename]&#xA;&#xA;Reads from stdin if the optional argument is missing.&#xA;&#xA;inputfile=&#34;${1:-/dev/stdin}&#34;&#xA;&#xA;cat &#34;$inputfile&#34; | sed &#39;1d&#39; | sed &#39;$d&#39;&#xA;&#xA;The script calls sed to delete the first and last line with the d command.&#xA;&#xA;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.&#xA;&#xA;#z80mbc2 #v20mbc #linux #retrocomputing&#xA;&#xA;a href=&#34;https://remark.as/p/journal.paoloamoroso.com/conversion-scripts-for-cp-m-file-transfers&#34;Discuss.../a&#xD;&#xA;Email | Reply @amoroso@oldbytes.space&#xD;&#xA;&#xD;&#xA;!--emailsub--]]&gt;</description>
      <content:encoded><![CDATA[<p>To code on the <a href="https://journal.paoloamoroso.com/tag:z80mbc2">Z80-MBC2</a> and <a href="https://journal.paoloamoroso.com/tag:v20mbc">V20-MBC</a> homebrew computers I often transfer text files to and from their CP/M environments.</p>

<p>In one direction I send files from Crostini Linux by <a href="https://journal.paoloamoroso.com/a-minimal-cp-m-file-transfer-channel">dumping them to CP/M</a>, where <code>PIP</code> saves the text to CP/M files. In the opposite direction I run <code>PIP</code> on CP/M to print the files to the screen, where Minicom captures the text and saves it to files on Crostini.</p>

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

<p>The first script, <code>unix2cpm</code>, converts line breaks and the end of file marker in the input to the CP/M encoding and prints the result to <code>stdout</code>. If the optional file name argument isn&#39;t supplied the script reads from <code>stdin</code> with a <a href="https://journal.paoloamoroso.com/how-to-make-bash-scripts-read-from-stdin">technique</a> I researched. This is the script:</p>

<pre><code class="language-bash">#!/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.

input_file=&#34;${1:-/dev/stdin}&#34;

cat &#34;$input_file&#34; | unix2dos
echo -e -n &#39;\x1a&#39;
</code></pre>

<p>The script calls <code>unix2dos</code> distributed with the <a href="https://waterlan.home.xs4all.nl/dos2unix.html">dos2unix / unix2dos</a> tools. <code>unix2dos</code> converts line breaks from Unix to MS-DOS, which borrows the encoding from CP/M. <code>unix2cpm</code> needs only to append with <code>echo</code> the <code>^Z</code> end of file control character.</p>

<p>Once converted, the file is ready to be <a href="https://journal.paoloamoroso.com/a-minimal-cp-m-file-transfer-channel">dumped from Linux to CP/M</a>.</p>

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

<pre><code class="language-msdos">A&gt;a:pip con:=filename.txt
</code></pre>

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

<p>To remove the unwanted first and last line