I tried out the new version of CMOC (1.45), which supports jump tables for switch-case statements. The emulator runs quite a bit faster with Altair BASIC. You can type in a short basic program without pausing between each key, and after pressing return, there is a much shorter pause before the machine becomes responsive again to enter the next line. I have only tried this with XROAR, as I need to download the new binary to the Coco... at 300 baud with CC-Kermit. I'm sure there are OTHER ways to get this into the physical hardware, but Kermit works well for me. CMOC also now supports 32-bit math 'long' types, so I should also be able to remove by hacks to the original i8080-core that did away with 32-bit math for the DAD instruction.
I was interviewed a couple nights ago for the CoCo Crew podcast. When that appears online, I'll drop a link here. I'm surprised people are interested in my weird hobbies. :-)
Unfortunately I have not had any time to progress any further in this project. However, I did take some time to make a slightly easier to follow Makefile and Readme than I had before, and I uploaded it all to GitHub. Repo Here
I was also contacted by the author of CMOC Pierre Sarrazin. He has linked back to my project, and put optimizing switch statements on his TODO list, so it is possible that this emulator may speed up without me doing anything at all. :-) I have also noticed that if you run xroar at maximum speed, the BASIC interpreter is quite usable, but still quite absurdly useless.
If anyone has trouble getting this to work, please send me an email. Its possible I missed a file or otherwise goofed something up packaging it all together.
Using C-Kermit for the CoCo (download link on their archive page) I transfered a 18K file to a physical floppy over a serial port at a whopping 300 bits per second. And then the file wouldn't run, because I accidently saved it as a TEXT file instead of a ML (machine language) file.
Bill Yakowenko's CoCo site has a very interesting program SAVEBA2.BAS which reads a CoCo disk sector by sector in BASIC and can rewrite the filetype of a file. His version modifies a file from TEXT to BASIC so that a BASIC program can write TEXT file to disk, and then modify the TEXT to be executable BASIC. A while back I wrote by own version of 'DIR' in BASIC using a similar technique, using his program and the manual as a guide. I got out the disk for that program, and modified it so I can modify directory entries and write them back to disk. I converted the file from TEXT to ML, and then it was executable. Why do to the trouble to do this? I wasn't going to wait to download it again at 300 baud, and this took slightly less time, about 10 minutes. You also may notice Yakowenko has a program that downloads at 9600 baud. Why didn't I use that? His program works great for text/basic files, but I found it unreliable for binary files. I used his program to copy CC-Kermit to my CoCo a couple years ago, but to get it to work, I encoded CC-Kermit into hex, downloaded it using his program, then wrote a program of my own to convert the hex to binary. I have an old post on the Vintage Computer Forum that outlines how to do this.
In the end, I have a working, but uselessly slow, copy of Altair BASIC running on the Color Computer:
At this point, I'd say I've succeeded at what I set out to do, I honestly didn't expect this to work. I thought there were just too many differences between C and CMOC, or that CMOC would be a buggy mess. A homemade C compiler for a computer no one uses anymore? CMOC works great! I barely had to do anything to the i8080-core emulator to get it to compile; I just moved a few things around and turned some macros into functions to make the executable smaller. In the next few days I'll clean up my code and put it on Github as a fork to i8080-core. I also might look to see if there is anything reasonable I can do to make it faster. There's also a million other enhancements that can be made such as using the floppy drive and running CP/M. To do that, I will need to access the upper 32k of the CoCo RAM, which disallows the use of the builtin ROM routines for video, keyboard, and disk. Perhaps I can just map in the top 32k of ram when running 8080 code, and then when there's a call to the emulated BIOS, map the ROM back in. It sound interesting, but also very crash prone, complicated, and may not fit in the retro challenge.
I got Altair 4k BASIC to start. I am having trouble with CMOC inkey() function crashing. I probably goofed something up. So no keyboard input yet.
I got 8080EX1.COM RUNNING:
This is running in xroar at maximum speed. It seems hung... but on my 4 Ghz PC it takes several seconds to proceed past the first test. It may take hours here. At first I thought it was hung, because the modern PC prints "DAD (registers) ..... OK" all at once. Then I remember line buffering, and yes, on my modern PC, when I add extra newlines in to the emulated CP/M routines, it prints DAD (registers) ...., then waits a few seconds, and then prints OK or error. So... this may take hours to get past the first test.
When I first tried this app it wouldn't start, because I exceeded the CoCo 32k memory limit. When using CMOC, the executable needs to fit within the bottom 32k of memory. (There are tricks to get data shadowed unter the ROM, but I'm not messing with that yet.) My first implementation had the program in a static array, and a seperate array for emulated ram, and it copies in tthe program. To save space, it now starts up with a single static array with the program already copied into the proper location.
For now, the maximum I can size (with the default CMOC memory origin and recommended limit allowance for the stack) is 0x1900 bytes of emulated RAM. That is 6.4k. The original Altair had 4k of memory, so I should be able to run 4k basic. (I believe the 4k in 4k basic means 4k machine, not that the interpreter takes all 4k. I will find out... )
I also want to mention this project Altair BASIC via 8080 emulation which I found when Googling around for 8080 and Altair BASIC stuff. It even uses the same emulator (a lot of people seem to use this one), so I will take a look inside their HAL code and see what is needed for console I/O.
It works! insert lots of fine print here
I got 8080PRE.COM to run to completion. There is a bug in the emulator I ported. It made a unportable assumption:
The emulator was careful to make readword and writeword macros to make sure that bytes in the emulated memory get written in the right order. But, when a word in read into a register pair struct, the reads are carefully swapped around, but the result in put into register pair that is not correctly swapped. The fix is to swap H and L structs order a big-endian machine, such as a 6809:
On a little endian machine such as x86, you can ignore a lot of details. Now consider the order on a big endian machine:
This is what I have set up now as a semi-sane workflow:
On the left side of the screen I have a Linux terminal running modified i8080_core fro Github. The modifications were made so the same source builds in both CMOC and GCC. On the bottom left is an xroar window running the CMOC version. Both programs output the same PC, (R)ead and (W)rite addresses, until a certain point. This is where the CMOC build acts differently than the Linux build. To troubleshoot this, on the right of the screen I have the original 8080 source code for 8080PRE.COM. I am comparing it to the disassembly of the same file so I know which addresses correspond to which instruction. BUT... the disassembler I found in the Arch LInux AUR only outputs Z80 assembly code. Now, the Z80 is just a "fancy" 8080, so it should all be the same for this simple test.
Ok, so I have decided what to do for this project. I have been looking online for a nicely written emulator for another microprocessor, like a Z80, 6502, somehthing like that.. I have found https://github.com/begoon/i8080-core. Will it compile under CMOC?
With some adjustment, it does compile under CMOC! The adjusted code in gcc still works on linux for the preliminary tests. Currently the DAD instruction in intentionally broken, as I haven't rewritten it for CMOC. (The implementation here uses 32-bit ints to emulate 16-bit math & carry). But does it run on the CoCo?
It crashes xroar! Turns out the program is too big. The emulator uses a lot of MACROS as a hack to simulate inline functions. So I replaced most of them with functions that do the same thing, and this brought in the executable size to something that doesn't crash the CoCo. (14k). But does it pass the CPU tests?
No! 8080PRE.COM does not run properly! But it doesn't die on the first test it does either, so the CoCo is at least running some 8080 instructions properly
But why am I trying to port a C program to CMOC to run 8080 programs on a CoCo? Why, to run Altair BASIC of course. But, the CoCo already has a faster, better, COLOR BASIC. Yeah but this is the retrochallenge, so I need to use my old computers to run even older computers at slower and more pathetic speeds.
I got CMOC to build. Automake and lwtools needed to be installed first. A simple hello world app:
Now, what am I going to be doing on this CoCo?
The retrochallenge has started. I am not completly sure what my project will be yet, but I am going to for now assume it is for the CoCo. I am trying to get a C cross-compiler environment set up for my TRS-80 Color Computer 2.
CMOC is a C subset compiler for the CoCo. So I will start with that.