• Please review our updated Terms and Rules here

I created floppy images of Scott Adams Adventure Games for CP/M on Nabu

I believe I have figured out the problem with ADVENTUR.COM hanging on certain versions of C128 CPM

At 0x0150, there is a "di" (disable interrupt, 0xf3), but there's no corresponding "ei" (enable interrupt, 0xfb).

If you change 0x150 to a NOP (0x00) there is no hang on C128 cpm.system.622-598666

To test using VICE:
1. set a break point for 0x150: bk 150
2. load CPM and then load ADVENTUR
3. after break happens, change 0x150 to NOP: a 0150 nop <enter twice to exit assemble mode>
4. exit monitor: x

There shouldn't be a hang.

Before I make a change to my 36 column (used to be 40 column), I'd like a sanity check on this.

If someone wouldn't mind testing some and/or verifying if there should be an "ei" somewhere I missed that would be helpful.
 
  • Like
Reactions: erd
I only just spotted the previous posting in this thread. Has anyone else tested this? Has anyone else looked through ADVENTUR.COM to look for DI/EI pairs?
 
Only took 13 months, but I just sat down and ground through all the versions of CP/M on zimmers and a) verified that it's that di instruction at 0x0150, and b) the versions from 1 AUG 85 *work* with the original program where it hangs on the 8 DEC 85 and 28 MAY 87 versions, and c) patching the di to a nop works on all versions.

I disassembled ADVENTUR.COM and as @jefferystone pointed out, there's a di and no ei. Anywhere. There's literally just one di that gets executed right after the opening banner is printed (prior to printing the first prompt) and there is not a corresponding ei, so it's not bracketing any sensitive code, the application just turns off interrupts and leaves them off.

I am nowhere near to being a CP/M Wizard so I have no idea what specific impact this kind of foolishness has except that across many platforms, it does or does not hang the BDOS call to read the console. The original app works fine on an emulated Altair running CP/M 1.4, runs fine on a Rainbow running whatever version of CP/M is out there to be grabbed (I cannot quickly check) and it runs on the oldest (of three) version of CP/M Plus 3.0 on the Commodore 128. Apparently it hangs on the Nabu then, without the di->nop patch?

Thanks, Jeffery, for running this down. When I looked at the disassembly, it kind of stood out but I'm late to the Z-80 game so I just didn't see it staring me in the face. For posterity, here's how it looks...

org 00100h

ld hl,l0109h ; point to welcome string
call sub_04e5h ; print out welcome string
jp l0150h ; jump past welcome string
l0109h: ;"<cr><cr>ADVENTURE BY SCOTT ADAMS..."
l0150h:
di ;0150 f3 <-- this guy is the problem
call sub_154ch ; getting on with the business of setting things up
 
I am nowhere near to being a CP/M Wizard so I have no idea what specific impact this kind of foolishness has except that across many platforms, it does or does not hang the BDOS call to read the console.
The 8080 doesn't have great interrupt support. CP/M itself doesn't require interrupts anywhere either; the BIOS interfaces are clearly designed for polled operation. Consequently, a lot of CP/M machines didn't bother with interrupts at all, so they don't care whether they are enabled or not.
 
  • Like
Reactions: erd
I ran into this the other way round when bringing up CP/M 3 recently - I found it crashed when I used SID, because SID enables interrupts and I hadn't got round to setting up the timer interrupt handler in bank 0. (I wasn't using interrupts for any other I/O, so I could do everything else with them disabled, and that's how the system was at boot)

It happens when SID hits a breakpoint; it disables interrupts to manipulate the stack, and then enables them afterwards. So I think, with SID at least, there is an assumption that (a) under CP/M and derivatives it's safe to enable interrupts, and (b) if in doubt they should be enabled rather than disabled.
Code:
breakp: ;arrive here when programmed break occurs
        di
        shld    hloc    ;hl saved
        pop     h       ;recall return address
        dcx     h       ;decrement for restart
        shld    ploc
;       dad sp below destroys cy, so save and recall
        push    psw     ;into user's stack
        lxi     h,2     ;bias sp by 2 because of push
        dad     sp      ;sp in hl
        pop     psw     ;restore cy and flags
        lxi     sp,stack-4;local stack
        push    h       ;sp saved
        push    psw
        push    b
        push    d
;       machine state saved, clear break points
        ei              ;in case interrupt driven io
 
The 8080 doesn't have great interrupt support. CP/M itself doesn't require interrupts anywhere either; the BIOS interfaces are clearly designed for polled operation. Consequently, a lot of CP/M machines didn't bother with interrupts at all, so they don't care whether they are enabled or not.

It does make sense that it would hang the console on a fair number of machines. Even though *CP/M* might not use interrupts itself the specific hardware might rely on it for keyboard handling or other such tasks. (CP/M programs themselves might use the polling interface, but under that there’s a type-ahead buffer or whatever that relies on interrupt driven keyboard handling; turn off the interrupts and keystrokes stop showing up.)
 
It does make sense that it would hang the console on a fair number of machines.
Obviously. I wonder how many machines would break, though. Especially on an 8080, supporting more than one IRQ isn't trivial. Neither BASIC nor CP/M 2.x benefit much from interrupts (not even timer ticks), so S-100 machines probably don't care. Even on an 8085 or Z80 with their much improved interrupt support, it may not be enough to justify the additional cost.

I've ported CP/M to the KC85/2-4 series (Z80) and they strictly require low-latency interrupts for keyboard and tape. Other machines probably do, too. But they may be the minority.

So I think, with SID at least, there is an assumption that (a) under CP/M and derivatives it's safe to enable interrupts, and (b) if in doubt they should be enabled rather than disabled.
Which are the smart assumptions: If a machine doesn't use interrupts, it shouldn't wire or enable any.
 
I've ported CP/M to the KC85/2-4 series (Z80) and they strictly require low-latency interrupts for keyboard and tape. Other machines probably do, too. But they may be the minority.

I just wonder why in the world a Scott Addams text adventure would ever touch interrupts, full stop. Maybe they wanted to disable the periodic interrupt that was present on a lot of machines (like disk-based TRS-80s) that's used for nothing besides updating the clock to keep someone from noticing how much time they were wasting... ;)
 
Nabu CP/M, for what it's worth, uses the interrupt for stuff like the cursor and keyboard polling.

It's not necessary; it's possible to code for "raw" Nabu such that interrupts aren't needed.
 
Back
Top