Note: This blog post was originally posted on drewdevault.com and has been cross-posted here.
There are several pieces of software in the toolchain that are required to write and test software for KnightOS:
You also need a copy of the latest kernel and any of your dependencies from packages.knightos.org. Getting all of this is not straightforward. On Linux and Mac, there are no official packages for any of these tools. On Windows, there are still no official packages, and you have to use Cygwin on top of that. The first step to writing KnightOS programs is to manually compile and install several tools, which is a lot to ask of someone who just wants to experiment.
All of the tools in our toolchain are written in C. We saw Emscripten as an opportunity to reduce all of this effort into simply firing up your web browser. It works, too! Here’s what was involved.
Note: Click the screen on the emulator to give it your keyboard. Click away to take it back. You can use your arrow keys, F1-F5, enter, and escape (as MODE).
Let’s start by showing you what we’ve accomplished. It’s now possible for curious developers to try out KnightOS programming in their web browser. Of course, they still have to do it in assembly, but we’re working on that 😉. Here’s a “hello world” you can run in your web browser:
We can also install new dependencies on the fly and use them in our programs.
Here’s another program that draws the “hello world” message in a window. You
You can find more packages to try out on packages.knightos.org. Here’s another example, this one launches the file manager. You’ll have to install a few packages for it to work:
Feel free to edit any of these examples! You can run them again with the Run button, of course. These resources might be useful if you want to play with this some more:
Note: our toolchain has some memory leaks, so eventually emscripten is going to run out of memory and then you’ll have to refresh. Sorry!
loaded this page, a bunch of things happened. First, the latest
release of the KnightOS
kernel was downloaded. Then all of the
emscripten ports of the toolchain were downloaded and loaded. The various
virtual filesystems were set up, and two packages were downloaded and installed:
core/kernel-headers. Extracting those packages involves
copying them into kpack’s virtual filesystem and running
When you click “Run” on one of these text boxes, the contents of the text box is
/main.asm in the assembler’s virtual filesystem. The package
installation process extracts headers to
/include/, and scas itself is run
/main.asm -I/include -o /executable, which assembles the program and
writes the output to
Then we copy the executable into the genkfs filesystem (this is the tool that
generates filesystem images). We also copy the empty kernel into this
filesystem, as well as any of the packages we’ve installed. We then run
/kernel.rom /root, which creates a filesystem image from
/root and bakes it
kernel.rom. This produces a ready-to-emulate ROM image that we can load
into the z80e emulator on the left.
cd build emconfigure cmake .. emmake make
The process was basically that simple for each piece of software. There were a few changes made to some of the tools to fix a few problems. The hard part came when I wanted to run all of them on the same page. Emscripten compiled code assumes that it will be the only emscripten module on the page at any given time, so this was a bit challenging and involved editing the generated JS.
The first thing I did was wrap all of the modules in isolated AMD loaders. You can see how some of this ended up looking by visiting the actual scripts (warning, big files):
That was enough to make it so that they could all run. These are part of a toolchain, though, so somehow they needed to share files. Emscripten’s FS object cannot be shared between modules, and their API for mounting filesystems is pretty crappy. So the solution was to write a little JS:
With this, we can extract packages in the kpack filesystem and copy them to the genkfs filesystem:
And this puts all the pieces in place for us to actually pass an assembly file through our toolchain:
This was fairly easy to put together once we got all the tools to cooperate.
After all, these are all command-line tools. Invoking them is as simple as
main and then fiddling with the files that come out. Porting z80e, on
the other hand, was not nearly as simple.
z80e is our calculator emulator. It’s also
written in C, but needs to interact much more closely with the user. We need to
be able to render the display to a canvas, and to receive input from the user.
This isn’t nearly as simple as just calling
main and playing with some files.
The result of that effort is that you can find out what the current value of a
, by the way).
I’ve put all of this together on try.knightos.org. The source is available on GitHub. It’s entirely client-side, so it can be hosted on GitHub Pages. I’m hopeful that this will make it easier for people to get interested in KnightOS development, but it’ll be a lot better once I can get more documentation and tutorials written. It’d be pretty cool if we could have interactive tutorials like this!
It was a lot of effort to make this happen, but it was worth it. This is some pretty cool shit we’ve got as a result.