This is an old revision of the document!
2022-09-18
This post is the first work I have created using the Memo application on the first HP 95LX that I recently acquired.
I did use Memo previously to create a few script files, mainly to start and configure lDebug.
I received this device 8 days ago (as of this writing), on 2022-09-10 Saturday. Last Friday, 2022-09-16, I picked up the serial connection cable that I ordered from the US. This has allowed me to exchange files between the 95LX and my desktop computer running Linux.
I already modified lDebug somewhat to work on the device. For one, I used a build of lCDebug that didn't hook interrupt 6. While on some 186 and probably all 286 systems interrupt 6 is used as an Invalid Opcode handler, this is not what it is used for on the 95LX. Instead it appears to host an interface specific to the device. The Interrupt List states that it is related to the sleep feature.
However, it appears to be called with a function number of 02h in the ah register within the DOS's handler for interrupt 21h service 0Ah. The Interrupt List does not specify what that means.
In any case, hooking interrupt 6 so as to return control to the debugger command line was a recipe for failure. In one case I managed to brick the 95LX so much so that even Ctrl-Alt-Del did not work any longer. I had to remove all the batteries and thus reset the device entirely.
I eventually extended lDebug so that it detects the 95LX using an interrupt 15h service 4DD4h. In case of a 95LX it will not hook interrupt 6.
Further, I added an assembly option flag (in the variable DAO) for NEC V20 disassembly repetition rules. This causes the R command to repeat disassembly after any mov instruction with a segment register, as well as a pop wtth any 186 segment register. This means that mov from any segreg, mov to ds or es, and pop ds and pop es will repeat disassembly which they do not in case the DAO flag is clear. Apparently the NEC V20 will lock out interrupts after all of these too, not only after pop or mov to ss. (This lock out is meant to allow atomically switching stacks, which requires setting both ss and sp without the possibility of an interrupt between the two needed instructions.)
Next up I am considering to add a 40-column friendly mode to the R, U, and D commands. The 95LX has a 40x16 screen, though it allows to scroll in a virtual 80x25 screen. Supposedly there is a way to get a 60-column mode, but I have not yet tried this.
Other than these hurdles the Datacomm application's XMODEM transfer as well as lDebug's serial I/O both work across the serial connection. (The serial port on the 95LX only has 4 pins, one of which each is unused, ground, receive, and transmit. So hardware flow control is not supported.)
I have also tested the performance of starting lCDebug in the uncompressed form, the LZSA2 compressed form, as well as the LZMA-lzip compressed form. Uncompressed the startup requires about 1 second. LZSA2 requires around 8 seconds. LZMA-lzip requires 166 seconds, or 2 minutes 46 seconds.
The hardware keyboard is a welcome novelty compared to the modern touch screen devices that we're used to. But the device fits comfortably in two hands regardless, allowing to type with the thumbs. This is why I wanted to try writing on the 95LX.
2022-09-19
I have modified lDebug's R and U commands today. The R command will switch to a 40-column display mode when both the DCO6 flag 1000h is set and the RX command was not used to enable 32-bit register display. Of course, I added a build option which makes it possible to omit the new handling at build time.
This display uses three lines to display all 186-level registers and most flags. The first line has AX, BX, CX, DX, and BP. The second line has CS, DS, ES, SS, and SP. The third line has IP, SI, DI, and some of the flags. Those are the Direction Flag (D = Down, U = Up), the Interrupt Flag (E = Enabled, D = Disabled), as well as the default two-letter states of the Overflow Flag, Sign Flag, Zero Flag, and Carry Flag. The Parity Flag and Auxilliary Carry Flag were considered so unimportant that they were omitted from the 40-column display, to avoid needing four lines. The normal (80-column style) symbolic Flags display can still be accessed using the R F command.
The U command observes the 40-column mode by using an adjusted "mnemonic offset". This value is usually 28, which allows for up to 8 bytes of machine code dumped per line (in a 16-bit code segment). In the 40-column mode the value is decreased to 20, allowing only 4 bytes of machine code per line. This makes many disassembled instructions fit onto the 40-column visible screen part, however it does not cover 100% of cases. Also, the referenced memory display and the jumping notices are still displayed so as to end before the 80th column.
One additional change I am considering is to no longer align the first operand of a disassembled instruction to the 8th column after the mnemonic offset. However, I anticipate that this may be a more complicated patch.
Another set of commands in dire need of a 40-column friendly mode is the D command family, that is the DB, DW, and DD commands. This may also prove more complicated than the R and U patches that are yet done.
The interactive E command mode can probably easily be adapted to be 40-column friendly.
The assembler, R variable, and default command line prompt interfaces are not in need of a 40-column mode other than setting R IOR := #40 which will make the debugger's rawinput line editor respect the narrower screen width. To make the debugger use that line editor, the DCO flag 8 (always assume InDOS) or DCO6 flag 200h (use ROM-BIOS I/O even when DOS available) should be set. Setting one of these also allows to highlight changed registers (DCO3 flag 4_0000h) without needing to install any ANSI escape sequence parser. (The 95LX video ROM-BIOS is detected as functional for this purpose.)
Next up I want to try running Public Domain ZModem on the 95LX. This has two possible failures in store for me: First, it may need hardware flow control which the 95LX cannot provide as it only has two pins on its serial interface, one each for transmit and receive. Second, it draws a colourful TUI window for its status and progress display. This may fail either if the screen memory is not as expected or if the colour combinations do not lead to readable output. If both of these problems turn out to be minor or nonissues then using the ZMODEM protocol may prove faster than the XMODEM protocol used by the Datacomm application, which appears to max out at 500 Bytes per second. (It also supports the Kermit protocol but I have not yet tried that.)
Other than that I intend to make a new lDebug release, numbered release 5, soon. Probably within this or the next month. There are a number of bugfixes as well as a few new features, such as the LFSR variables, the INT8CTRL variable, device driver mode for loading from CONFIG.SYS, RC buffer commands, and pointer-type as well as signed/unsigned expression types.
The next stages of lDebug are twofold: First, the symbolic build and its support script, codenamed Allegory. We recently enabled building with the symbolic option (formerly the symbolic branch) without having to sacrifice any other features, by splitting the code segment into two segments. These can call into one another with far calls or far-like calls. In the non-DPMI builds these calls can be assembled to far immediate calls that are relocated during initialisation. In the DPMI builds it is instead necessary to make far-like calls using thunk helper functions for both calls and returns that may cross the segment boundary. What is still missing is better support of symbol relocation and deletion as well as improved scripts for converting map files to script for lDebug (.sld) files.
The other direction is to re-use the windowed user interface of the Insight debugger (under GNU GPL v2-or-later) to control lDebug across a serial connection. To that purpose I have already added Eric Auer's Terminal as a feature to Insight, with some assumptions that match how lDebug behaves on its serial I/O. This still needs to have some rough edges improved, such as the unneeded jam handling code and deleting lines completely overwritten using Carriage Return followed by enough printable codepoints. The code name for this project is Einsicht, which is Insight in German. Ideally this would replicate or exceed all features provided by Insight as yet, with extensions specific to lDebug. As a last resort, the lDebug interface could be accessed directly in Einsicht's Terminal window. The expected use case is to connect two VMs (dosemu2 or qemu) on a Linux host using emulated serial interfaces, though in a pinch either or both could be physical machines too.