When I first heard about the utter hackability of the Sega Dreamcast, it immediately became a geek fantasy of mine to see QNX running on it. (Cool things running on odd platforms is an obsession of mine, for example, not too long before I tackled this, I ported robotfindskitten to the Commodore 64 and Apple II.) So I managed to track down and buy a Dreamcast. Several months later, I even went so far as to purchase a serial cable, so that I could transfer programs to it without burning CDs. Finally, one day I brought it up to my boss, Rick Duff, that I'd always wanted to see QNX running on this Dreamcast. And the rest is history. Yet to be written.
There is still a small problem wherein my mouse and keyboard drivers don't seem to want to coexist, but I'm sure it's quite simple to fix. I decided that rather than tackle that problem, I would make the keyboard driver work. And at the moment, it works near-flawlessly. Repeat isn't simulated, so I have to hit backspace a bunch of times if I want to delete something, etc. Also, I'm having some funny problems with the arrow keys in this terminal window which I don't quite understand. (The keypad arrows work great, though..)
Once I fix the bug in my maple framework and can use the mouse and keyboard simultaneously, I will be able to use QNX on the Dreamcast without requiring a serial connection. (I still require my laptop to be running and online so that I can run everything over QNET -- that won't change until I write a GD-ROM driver.) A very exciting development indeed!
Someone sent me an email asking if I've got a mailing list set up so that they could be notified when this page was updated. Well, I don't, but if there's some demand, I'll set one up. Send me an email if you're interested in being notified of updates to this page.
As a first test of my Maple framework, I have a mouse driver which works nicely. Check out this screenshot of me browsing the Boob! forums. It's such a nice feeling to finally be able to interact directly with my Dreamcast, rather than over a serial port. I'm sorely missing my keyboard, so I imagine that'll be next. I'm still debating on how best to utilize the Dreamcast controller; I'm imagining the analogue stick as a mouse, and the ability to map keypresses to various buttons, but efficient keyboard-like input is an interesting problem. I want something sort of like Palm's Graffiti -- something with a bit of a learning curve, but fast enough that you can reasonably use it for pretty much everything once you've learned it. If anyone has any suggestions (or already-proven methods), please toss me an email and let me know!
I'm beginning work on a Maple driver for input. It's annoying that I seem to have to poll my devices, but at least with the DMA features, I can keep it to a minimum. (After all, what's the difference between a timer interrupt going off at 60hz and the mouse interrupting you 60 times a second?) It's the keyboard I'm really worried about, since I've had problems in some DC programs with it not polling fast enough for my 80wpm typing. But I guess the bus really wasn't designed with a keyboard in mind, and I'll have to deal with that as best as I can.
I've been sort of tinkering with a CD-ROM driver, but QNX's block filesystem code isn't documented or even generally distributed. I've read that the GD-ROM interface is actually IDE, and so I've been reading up on ATA/ATAPI a bit to see if I can use QNX's existing IDE driver somehow, but I'm not sure that the registers are the same as what QNX's driver expects. It almost seems like it's poking the registers to its satisfaction, but isn't getting an interrupt; it takes a while to timeout when I give it the proper register address. But it could simply be that it's sending it weird messages that the GD-ROM simply isn't equipped to understand. Hard to say, without the source.
Anyway, I should be picking up yet another replacement Dreamcast right away (one that works, this time) and showing you some nifty Photon screenshots very soon.
Here we can clearly see the Dreamcast wandering around my laptop's filesystem over QNET, and pinging google.com. There was a strange problem where I couldn't talk to my Dreamcast over QNET, but apparently that's because QNET acts weird with alignment fault emulation. Building a new boot script that disabled that fixed the problem. You'll also see that I'm using Rob Krten's ramdisk filesystem; it's been absolutely invaluable. My alternative was to shove everything into /dev/shmem, and since io-net expects to find drivers in /lib/dll, that would have been a problem. =]
The ASIC interrupt problem was solved, with much help from CyRUS64, who has done a great deal of reverse engineering of the Dreamcast for his Dreamcast emulator, Icarus. I didn't realize how sparse documentation for the Dreamcast hardware was until I took this on; thankfully, there are still some knowledgable individuals who'll take the time to help out.
I think I'm going to go collapse, now. It's been two solid weeks of work, but it's finally up and running. =]
My Dreamcast has also recently decided not to output a video signal anymore, so I'm hoping to score a replacement for cheap from eBay. This doesn't hold up BBA production, but once that's up and going, Photon is next. Also, I miss my Jet Grind Radio. =]
I've been playing with Marcus' "Hello, world" example for some time, but I was trying to use it in its assembly-language form. As the assembly code accesses memory directly, I had to do some serious kludging to wedge in the proper mmap_device_memory calls. This was generally unsuccessful, results ranging from no video output to segment violations to even kernel panics! (I'd certainly never seen a QNX kernel panic before -- I assume this is due to an undiscovered bug in my startup-dc program.) Once I decided to convert it into C code, it only took a few hours of work to get it up and running.
RC5 (Generic RC5 core): 14,131 keys/sec
OGR (GARSP 5.13): 367,425 nodes/sec
Just for reference, my K6/2 350MhZ desktop PC (although to be fair, the Dreamcast is only 200MhZ) scored:
RC5 (RG RISC-rotate II): 572,788 keys/sec
OGR (GARSP 5.13-A): 1,538,279 nodes/sec
Also, to be fair, I don't think there is an SH4 assembly core, so it'd be dealing with the unoptimized ANSI C core.
Nothing more to report; school started last week, my girlfriend got back in town last week, and one of our customers is in town this week, so forgive me if progress is slow. A broadband adapter is supposedly in the mail, meaning, of course, that it may soon be feasable to have network up and running under QNX.
Here is a pretty screenshot:
You may notice from the output of "pidin in" that the boot time is the
UNIX epoch. This is because the Dreamcast doesn't use a standard SH4
realtime clock, and I have yet to write the code to use the RTC actually
in the Dreamcast.
I'm currently using Marcus Comstedt's Serial upload slave to send the images over the serial port, as porting the dcload-serial client, which allows for such things as compression and "not sending the data using the bloated SREC format", to QNX proved difficult. Burning this image to a CD should prove trivial, as the Dreamcast BIOS should load the QNX image automatically. Hooray for not having to write an IPL!
In fact, the job was actually fairly easy. Despite having never done anything like this before, I found QNX's BSP stuff to be quite easy to work with. Basically, I had to take the startup- program of one of the existing SH boards (I picked the Solution Engine, as it seemed the most generic of my choices) and funge it to report where the Dreamcast maps its devices, user RAM, etc.
The hardest part of this was probably getting some semblance of debugging output working; I never managed to get the built-in serial debugging output to work! Instead, I hacked together my own "debug driver" which displayed the debugging output to the screen. This meant I got a TV in my office for a few days =] One interesting hangup I had was that when I specified where the user RAM was, my screen output a garbage character and hung. Turns out that the bios routines that I was using to get the font data were located in the first 32kb of RAM. Oops. =]
So, that's about as impressive as it gets at the moment. Now begins the ever-so-fun task of writing driver after driver =]