{"id":1759,"date":"2017-12-03T08:40:02","date_gmt":"2017-12-03T08:40:02","guid":{"rendered":"http:\/\/www.sydneysmith.com\/wordpress\/?p=1759"},"modified":"2018-11-10T01:05:40","modified_gmt":"2018-11-10T01:05:40","slug":"running-cromix-on-windows","status":"publish","type":"post","link":"https:\/\/www.sydneysmith.com\/wordpress\/1759\/running-cromix-on-windows\/","title":{"rendered":"Running Cromix on Windows"},"content":{"rendered":"<p><img loading=\"lazy\" src=\"http:\/\/www.sydneysmith.com\/wordpress\/wp-content\/uploads\/2017\/12\/cromix-ps.png\" alt=\"\" width=\"677\" height=\"343\" class=\"alignnone size-full wp-image-1760\" srcset=\"https:\/\/www.sydneysmith.com\/wordpress\/wp-content\/uploads\/2017\/12\/cromix-ps.png 677w, https:\/\/www.sydneysmith.com\/wordpress\/wp-content\/uploads\/2017\/12\/cromix-ps-300x152.png 300w\" sizes=\"(max-width: 677px) 100vw, 677px\" \/><\/p>\n<p>Cromix is a multi-user, multi-tasking operating system &#8211; for the Z80!<\/p>\n<p>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&#8217;t be done because:<!--more--><\/p>\n<p>&#8211; the Z80 is a microprocessor not a minicomputer<br \/>\n&#8211; users need memory and the Z80 has a 64K ceiling<br \/>\n&#8211; programs typically (at the time) took about 32KB each<br \/>\n&#8211; it doesn&#8217;t have a supervisor mode<br \/>\n&#8211; it doesn&#8217;t support virtual memory<br \/>\n&#8211; and on<\/p>\n<p>As you can see in the picture above, someone (Cromemco) went and did it anyway. It also worked, and worked well.<\/p>\n<p>In some ways, cromix was linux before linux was invented. You see, unix was legally constrained so you couldn&#8217;t just port the software. There&#8217;s more on that on wikipedia under the background of <a href=\"https:\/\/en.wikipedia.org\/wiki\/Linux\">linux<\/a> 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&#8217;t actually unix &#8211; it is similar, but not quite the same.<\/p>\n<p>If you&#8217;ve used cromix before, using it again will be second nature. However, if you&#8217;re like me (always wanted to but couldn&#8217;t get my hands on it), you may find &#8220;close to but not unix&#8221; will trip you up in places. Here&#8217;s some hints:<\/p>\n<p>&#8211; instead of cat (unix for CP\/M type) or type (CP\/M for unix cat), there&#8217;s &#8220;ty&#8221;<br \/>\n&#8211; instead of cd or chdir to change directory, there&#8217;s &#8220;d&#8221;<\/p>\n<p>Other things work as expected: &#8220;ps&#8221; (example in the picture) for process status, &#8220;mount&#8221;, &#8220;umount&#8221;, &#8220;ls&#8221;, &#8220;ls -l&#8221;, even &#8220;l&#8221;.<\/p>\n<p>There is a &#8220;\/dev&#8221; directory, and &#8220;\/etc&#8221; and &#8220;\/bin&#8221;. There is an &#8220;\/etc\/passwd&#8221; file and so on. Close, but different. I really recommend getting a <a href=\"https:\/\/amaus.org\/static\/S100\/cromemco\/cromix\/Cromemco%20Cromix%20Instruction%20Manual%20023-4022%20198212.pdf\">copy of the manual<\/a> (pdf).<\/p>\n<p>You can download a copy of z80sim with the necessary hardware configuration and a boot disk from <a href=\"http:\/\/www.sydneysmith.com\/products\/cpm\/z80sim\/run-cromix1127.zip\">cpm\/z80sim\/run-cromix1127.zip<\/a>. (You can also run it in the ZEMU emulator by Wiley J Moore if you follow Marcus&#8217; instructions <a href=\"https:\/\/majzel.blogspot.com.au\/2014\/03\/running-cromemco-cromix-inside-z80.html\" rel=\"noopener\" target=\"_blank\">running-cromemco-cromix-inside-z80.html<\/a>). Mine&#8217;s easier to setup and run, but it isn&#8217;t yet as rock-solid as the ZEMU one.<\/p>\n<p>On the way, there were a few lessons learnt.<\/p>\n<h2>&#8220;Unable to open console&#8221;<\/h2>\n<p>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&#8217;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&#8217;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 &#8211; at least in a unix environment. His cromemcosim files had an equivalent line doing the same.<\/p>\n<h2>&#8220;Not supported bank select&#8221;<\/h2>\n<p>This was one of those &#8220;it will never occur&#8221; messages. It was in the 256KZ software I added a little while back. It happens when you select a memory bank that doesn&#8217;t exist. Cromix happily works its way through all of the memory banks, even those that don&#8217;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&#8217;ve changed the 256KZ software to select bank 0 for unused slots. If you&#8217;re copying the (later) software, you can change a &#8220;#define&#8221; to include more than 4 x 64K on a 256KZ card and the software will adjust the &#8220;built-in \/ virtual&#8221; switch settings for you. There isn&#8217;t a runtime switch selection.<\/p>\n<h2>&#8220;Cannot initialize STDC controller&#8221;<\/h2>\n<p>Marcus&#8217; &#8220;Load Cromemco RDOS (Resident Disk Operating System) monitor, version 03.12&#8221; line seems pretty routine; but it is not. If you&#8217;re not careful you&#8217;ll try and boot a non-existent hard disk. RDOS changed over the years from &#8220;b&#8221; to boot (drive A) to &#8220;b&#8221; to boot the drive set by the &#8220;unused&#8221; DIP switches on the 16FDC card, to boot from hard disk. His picture in the article shows &#8220;bb&#8221; to boot from disk B. &#8220;ba&#8221; is the RDOS0312 equivalent of the earlier &#8220;b&#8221;. However there&#8217;s more to this than meets the eye &#8230;<\/p>\n<h2>Invalid Opcode at &#8230; or Hanging<\/h2>\n<p>These are both indicative of interrupt driven systems going awry. However, it wasn&#8217;t that at all. Marcus&#8217; 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&#8217;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&#8217;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&#8217;, you&#8217;ll load nothing and run random memory.<\/p>\n<p>Marcus&#8217; solution, or unsuspecting luck, was to run RDOS first. That sets CY and A&#8217;.<\/p>\n<p>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 &#8220;JR C,&#8230;&#8221; 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&#8217;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).  <\/p>\n<h2>Running CP\/M Under Cromix<\/h2>\n<p>There is evidence to suggest that this is possible. One of the programs on the Cromix disk is &#8220;debug.com&#8221; &#8211; a CDOS program. The cromix ones end in &#8220;.bin&#8221;.<\/p>\n<p>If you run debug you get the familiar CDOS debug prompt:<br \/>\n<code><\/p>\n<pre>\r\n#\r\n# debug\r\nDEBUG version 00.17\r\n-\r\n<\/pre>\n<p><\/code><br \/>\nThere is nothing at 0100H, but there is at 0000H:<br \/>\n<code><\/p>\n<pre>\r\n-d\r\n0100   00 00 00 00  00 00 00 00  00 00 00 00  00 00 00 00  ................\r\n0110   00 00 00 00  00 00 00 00  00 00 00 00  00 00 00 00  ................\r\n0120   00 00 00 00  00 00 00 00  00 00 00 00  00 00 00 00  ................\r\n0130   00 00 00 00  00 00 00 00  00 00 00 00  00 00 00 00  ................\r\n0140   00 00 00 00  00 00 00 00  00 00 00 00  00 00 00 00  ................\r\n0150   00 00 00 00  00 00 00 00  00 00 00 00  00 00 00 00  ................\r\n0160   00 00 00 00  00 00 00 00  00 00 00 00  00 00 00 00  ................\r\n0170   00 00 00 00  00 00 00 00  00 00 00 00  00 00 00 00  ................\r\n-d0\r\n0000   C3 03 E9 FF  FF C3 00 C7  C3 F5 FD FF  FF FF FF FF  C.i..C.GCu}.....\r\n0010   FF FF FF FF  FF FF FF FF  FF FF FF FF  FF FF FF FF  ................\r\n0020   FF FF FF FF  FF FF FF FF  FF FF FF FF  FF FF FF FF  ................\r\n0030   A8 EB 17 FF  FF FF FF FF  C3 0A FE FF  FF FF FF FF  (k......C.~.....\r\n0040   01 00 ED FB  00 00 00 00  00 00 00 00  00 00 00 00  ..m{............\r\n0050   00 00 00 00  00 00 00 00  00 00 00 00  00 20 20 20  .............\r\n0060   20 20 20 20  20 20 20 20  00 00 00 00  00 20 20 20          .....\r\n0070   20 20 20 20  20 20 20 20  00 00 00 00  00 00 00 00          ........\r\n-\r\n<\/pre>\n<p><\/code><br \/>\nThose 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:<br \/>\n<code><\/p>\n<pre>\r\n-le900\r\nE900  JP   E92D\r\nE903  JP   E934\r\nE906  JP   EDEB\r\nE909  JP   EDFE\r\nE90C  JP   EE28\r\nE90F  JP   E937\r\nE912  JP   E942\r\nE915  JP   E94D\r\nE918  JP   E92D\r\nE91B  JP   E92D\r\nE91E  JP   E92D\r\nE921  JP   E92D\r\nE924  JP   E92D\r\nE927  JP   E92D\r\nE92A  JP   E92D\r\nE92D  LD   HL,E955\r\n-l\r\nE930  LD   B,02\r\nE932  JSYS 1B\r\nE934  JP   EE2C\r\nE937  PUSH BC\r\nE938  PUSH DE\r\nE939  LD   E,C\r\nE93A  LD   C,05\r\nE93C  CALL EA91\r\nE93F  POP  DE\r\nE940  POP  BC\r\nE941  RET\r\n<\/pre>\n<p><\/code><br \/>\nThat is clearly a BIOS jump table. I also especially liked the &#8220;JSYS 1B&#8221; opcode. Here is a debugger that understands cromix system calls. In a less knowledgeable disassembler, that will be &#8220;RST 8&#8221; 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&#8217;ve been there.<\/p>\n<p>JSYS 1B is &#8220;.printf&#8221;. The message at E955 says &#8220;Unimplemented CPM jump at address %04.4xH\\r\\n\\0&#8221;. They&#8217;re not all unimplemented.<\/p>\n<p>This is part of the <a href=\"http:\/\/www.sydneysmith.com\/wordpress\/cpm-programs\/\">CP\/M topic<\/a>.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Cromix is a multi-user, multi-tasking operating system &#8211; 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&#8217;t be done because:<\/p>\n","protected":false},"author":3,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":[],"categories":[16,59],"tags":[74,73],"_links":{"self":[{"href":"https:\/\/www.sydneysmith.com\/wordpress\/wp-json\/wp\/v2\/posts\/1759"}],"collection":[{"href":"https:\/\/www.sydneysmith.com\/wordpress\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.sydneysmith.com\/wordpress\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.sydneysmith.com\/wordpress\/wp-json\/wp\/v2\/users\/3"}],"replies":[{"embeddable":true,"href":"https:\/\/www.sydneysmith.com\/wordpress\/wp-json\/wp\/v2\/comments?post=1759"}],"version-history":[{"count":3,"href":"https:\/\/www.sydneysmith.com\/wordpress\/wp-json\/wp\/v2\/posts\/1759\/revisions"}],"predecessor-version":[{"id":1774,"href":"https:\/\/www.sydneysmith.com\/wordpress\/wp-json\/wp\/v2\/posts\/1759\/revisions\/1774"}],"wp:attachment":[{"href":"https:\/\/www.sydneysmith.com\/wordpress\/wp-json\/wp\/v2\/media?parent=1759"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.sydneysmith.com\/wordpress\/wp-json\/wp\/v2\/categories?post=1759"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.sydneysmith.com\/wordpress\/wp-json\/wp\/v2\/tags?post=1759"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}