I was wrong. The HP-65 microcode available on the internet works fine. See HP-65 R/S. It’s the emulators that are broken (slightly). See HP-65 Delayed Select Group. Here’s how I fixed mine:
This will be in JavaScript for those that speak the language. The usual implementation of “delayed select group” is:
function dlyselgrp(num) { return function () { dlygrp = num; }; } function goto(addr) { return function () { if (prevCarry != 1) { ... romchip = dlyrom; grp = dlygrp; } }; } function jsb(addr) { return function () { ... }; } function setrom(num) { return function () { romchip = num; dlyrom = romchip; grp = dlygrp; }; }
Interestingly, I was also wrong about “jsb”. It isn’t affected at all (per this) by the “delayed select group”.
The “delayed select group (n)” saves (n) somewhere and, later on, a “goto” or a “rom” microinstruction causes a branch which then uses the saved group (n).
If you look at the microcode for the HP-65, you’ll almost always see a “delayed select group” followed immediately with a “goto” or a “rom” instruction. But not always.
It had been assumed – by me, and obviously by those that did the earlier code – that “delayed select group” sets up the value, and “goto/rom” carries it out. But that is wrong (see HP-65 Delayed Select Group). Some people figured that out before me and we’re all better off as a result.
The trick to getting the “delayed select group” microinstruction to work in those few cases when it isn’t followed by “goto/rom”, is something like this:
function dlyselgrp(num) { return function () { dlygrp = num; dgs=1; }; } // and in the Control And Timing chip emulation: var dgs = 0; // "delayed group select" state. // 0=off, 1=on, 2=pending, 3=act // microcode processing loop ... rom[grp*2048 + romchip*256 + pc++](); pc %= 256; // wrap back to beginning of the ROM // delayed group select if (dgs > 0) dgs++; if (dgs == 3) { grp=dlygrp; dgs=0; } ...
The lines using the “dgs” variable are the only additions. When a “delayed group select” microinstruction is executed, it saves (n) like before; but it also sets its state to 1=on.
After that instruction finishes, the “if (dgs …) dgs++;” increments the state to 2=pending. The next instruction executes normally.
After that one, we do dgs++ again and get to 3=act. At that point we set the group to the saved value ((n) aka dlygrp) and turn things off again (dgs=0 (=off)).
There are probably other ways to do the same but this one works. I’ve tried it with the original microcode and [R/S]. I’ve tried my usual test cases (just basics: key in a digit, ENTER, key in another, +, [A] (ie 1/x), etc).
I’ve left the existing code alone. That was working. Some of it is probably redundant now and there may be some strange bits that got added to offset the “delayed select group” not working as expected. (There is code to trigger a group change if you set s0 to 1. That might only be there because a “1 -> s0” happened to follow a “delayed select group” somewhere.)
The same approach could be used for other emulators written in C or Java – javascript ports pretty well to those. The code is licensed under GPL so feel free to use any of the above in any other emulator.
I’ve updated my HP65 emulator to version 1.01 (Menu / About), and refitted the original microcode and the above tweaks. As usual, you can access the emulator from my HP65 page.
The “1 -> s0” sequence guessed above, does exist. It is in group 1, rom 1, address 351.
This and the 01103 c<->m instruction are the only two instances in the microcode where delayed select group isn’t immediately followed by a goto or a rom microinstruction.