Running Cromix on Windows

Cromix is a multi-user, multi-tasking operating system – for the Z80!

It shocked me at the time that anyone would think of such a thing, much less attempt something so clearly far beyond the realms of possibility. It can’t be done because:

– the Z80 is a microprocessor not a minicomputer
– users need memory and the Z80 has a 64K ceiling
– programs typically (at the time) took about 32KB each
– it doesn’t have a supervisor mode
– it doesn’t support virtual memory
– and on

As you can see in the picture above, someone (Cromemco) went and did it anyway. It also worked, and worked well.

In some ways, cromix was linux before linux was invented. You see, unix was legally constrained so you couldn’t just port the software. There’s more on that on wikipedia under the background of linux so Linus Torvalds wrote his own from scratch. Cromix seems to have a similar background. Certainly it was the unix for Z80 of the time. But it wasn’t actually unix – it is similar, but not quite the same.

If you’ve used cromix before, using it again will be second nature. However, if you’re like me (always wanted to but couldn’t get my hands on it), you may find “close to but not unix” will trip you up in places. Here’s some hints:

– instead of cat (unix for CP/M type) or type (CP/M for unix cat), there’s “ty”
– instead of cd or chdir to change directory, there’s “d”

Other things work as expected: “ps” (example in the picture) for process status, “mount”, “umount”, “ls”, “ls -l”, even “l”.

There is a “/dev” directory, and “/etc” and “/bin”. There is an “/etc/passwd” file and so on. Close, but different. I really recommend getting a copy of the manual (pdf).

You can download a copy of z80sim with the necessary hardware configuration and a boot disk from cpm/z80sim/run-cromix1127.zip. (You can also run it in the ZEMU emulator by Wiley J Moore if you follow Marcus’ instructions running-cromemco-cromix-inside-z80.html). Mine’s easier to setup and run, but it isn’t yet as rock-solid as the ZEMU one.

On the way, there were a few lessons learnt.

“Unable to open console”

This was surprising because it was displayed on the console. An internet search turned up one other person who had the problem and some people who remembered having seen it before (on a real system probably) but couldn’t remember the solution. It turned out (after tracing through the code), that cromix was checking bit D2 of IO port 00, the console/UART status register. This bit is supposed to be high if the UART is connected to a serial terminal. None of the CP/M or CDOS versions I’ve seen check that; but cromix did. The solution for me was to modify the emulator to report this bit as high. Of interest, I suspect that Udo probably already has, or had, z80sim working with cromix – at least in a unix environment. His cromemcosim files had an equivalent line doing the same.

“Not supported bank select”

This was one of those “it will never occur” messages. It was in the 256KZ software I added a little while back. It happens when you select a memory bank that doesn’t exist. Cromix happily works its way through all of the memory banks, even those that don’t exist. If you read the fine print on the memory card manuals (normal print really), you are supposed to change switch settings to make bank 0 appear in the missing slots. My fault and easily fixed. I’ve changed the 256KZ software to select bank 0 for unused slots. If you’re copying the (later) software, you can change a “#define” to include more than 4 x 64K on a 256KZ card and the software will adjust the “built-in / virtual” switch settings for you. There isn’t a runtime switch selection.

“Cannot initialize STDC controller”

Marcus’ “Load Cromemco RDOS (Resident Disk Operating System) monitor, version 03.12” line seems pretty routine; but it is not. If you’re not careful you’ll try and boot a non-existent hard disk. RDOS changed over the years from “b” to boot (drive A) to “b” to boot the drive set by the “unused” DIP switches on the 16FDC card, to boot from hard disk. His picture in the article shows “bb” to boot from disk B. “ba” is the RDOS0312 equivalent of the earlier “b”. However there’s more to this than meets the eye …

Invalid Opcode at … or Hanging

These are both indicative of interrupt driven systems going awry. However, it wasn’t that at all. Marcus’ comment to use RDOS was either a happy coincidence for him or the result of what would have been a few frustrating hours. It turns out that the boot sector in cromix assumes a few things. That’s strange for a boot sector as it is normally the first step of loading an operating system. If you disassemble the boot sector, you’ll find it skips a few steps if the CY flag is set. It looks like this allows RDOS (for example) to override the normal boot device, eg boot from drive A and then load the rest from drive B (or H etc). If you get the wrong combination of CY and data in A’, you’ll load nothing and run random memory.

Marcus’ solution, or unsuspecting luck, was to run RDOS first. That sets CY and A’.

I wanted to be able to boot immediately so I typically copy the boot sector to a hex file and then start the simulator with that. After patching out the “JR C,…” instruction and recalculating the hex format checksum (twice, I was doing it by hand and got it wrong the first time), it booted reliably every time. I really thought I’d solved all of the instability issues at that point as it ran flawlessly enough from that point for me to package and release it (over 20 more tests). But there is still something else to find and fix, sorry. (It seems more temperamental after I started closing down windows processes so perhaps it is load / timing related).

Running CP/M Under Cromix

There is evidence to suggest that this is possible. One of the programs on the Cromix disk is “debug.com” – a CDOS program. The cromix ones end in “.bin”.

If you run debug you get the familiar CDOS debug prompt:

#
# debug
DEBUG version 00.17
-


There is nothing at 0100H, but there is at 0000H:

-d
0100   00 00 00 00  00 00 00 00  00 00 00 00  00 00 00 00  ................
0110   00 00 00 00  00 00 00 00  00 00 00 00  00 00 00 00  ................
0120   00 00 00 00  00 00 00 00  00 00 00 00  00 00 00 00  ................
0130   00 00 00 00  00 00 00 00  00 00 00 00  00 00 00 00  ................
0140   00 00 00 00  00 00 00 00  00 00 00 00  00 00 00 00  ................
0150   00 00 00 00  00 00 00 00  00 00 00 00  00 00 00 00  ................
0160   00 00 00 00  00 00 00 00  00 00 00 00  00 00 00 00  ................
0170   00 00 00 00  00 00 00 00  00 00 00 00  00 00 00 00  ................
-d0
0000   C3 03 E9 FF  FF C3 00 C7  C3 F5 FD FF  FF FF FF FF  C.i..C.GCu}.....
0010   FF FF FF FF  FF FF FF FF  FF FF FF FF  FF FF FF FF  ................
0020   FF FF FF FF  FF FF FF FF  FF FF FF FF  FF FF FF FF  ................
0030   A8 EB 17 FF  FF FF FF FF  C3 0A FE FF  FF FF FF FF  (k......C.~.....
0040   01 00 ED FB  00 00 00 00  00 00 00 00  00 00 00 00  ..m{............
0050   00 00 00 00  00 00 00 00  00 00 00 00  00 20 20 20  .............
0060   20 20 20 20  20 20 20 20  00 00 00 00  00 20 20 20          .....
0070   20 20 20 20  20 20 20 20  00 00 00 00  00 00 00 00          ........
-


Those are jump vectors into the BIOS at 0000H and into CP/M or CDOS (probably into the CDOS emulator) at 0005H. Looking into the BIOS gives:

-le900
E900  JP   E92D
E903  JP   E934
E906  JP   EDEB
E909  JP   EDFE
E90C  JP   EE28
E90F  JP   E937
E912  JP   E942
E915  JP   E94D
E918  JP   E92D
E91B  JP   E92D
E91E  JP   E92D
E921  JP   E92D
E924  JP   E92D
E927  JP   E92D
E92A  JP   E92D
E92D  LD   HL,E955
-l
E930  LD   B,02
E932  JSYS 1B
E934  JP   EE2C
E937  PUSH BC
E938  PUSH DE
E939  LD   E,C
E93A  LD   C,05
E93C  CALL EA91
E93F  POP  DE
E940  POP  BC
E941  RET


That is clearly a BIOS jump table. I also especially liked the “JSYS 1B” opcode. Here is a debugger that understands cromix system calls. In a less knowledgeable disassembler, that will be “RST 8” followed by a seemingly random instruction. It is always a single byte but other disassemblers will get lost if it looks like the start of a two or three byte opcode. I’ve been there.

JSYS 1B is “.printf”. The message at E955 says “Unimplemented CPM jump at address %04.4xH\r\n\0”. They’re not all unimplemented.

This is part of the CP/M topic.

It's only fair to share...Share on FacebookTweet about this on TwitterShare on Google+Share on LinkedInShare on StumbleUponDigg thisPin on PinterestEmail this to someone

2 thoughts on “Running Cromix on Windows”

  1. Correct, the UART status must be set if a terminal is connected, I needed a while too for figuring out what the Cromemco tty drivers are doing. For telnet consoles it is important to set the flag if a telnet connects, and reset the flag if it disconnects, else the getty processes will consume CPU time instead of going to sleep.

    Cromix provides a CDOS call interface sim.bin, so many CP/M programs will run. Then there is a CP/M emulation program sim22.com that provides a somewhat better CP/M call interface. Markus has the program and PDF manual and it’s installed on the z80pack cromix_work disk in /bin.

    Telnet consoles also aren’t working under Windows with the Cygwin z80pack machine. The problem is that Windows for some reason doesn’t generate signal SIGIO when a BSD socket connects. One would have to implement polling to check the sockets for incoming connections to accept them, and that is very nasty. The z80pack cpmsim machine supports SIGIO interrupt handling as well as polling for the sockets. For example MP/M works with multiple telnet terminals on Windows, but if you look at the source, oh my. I think I’ll just wait until Microsoft implements better BSD sockets.

Leave a Reply

Your email address will not be published. Required fields are marked *