[FYI: Matt Hellige’s excellent GoForth runs on this]

I’m completely astonished at how quickly a community has sprung up around Notch’s DCPU-16. In the first 24 hours there were already tens of implementations in various languages (including mine). Now there’s a web-based IDE, a whole C compiler/assembler tool chain, an LLVM backend, … It’s craziness!

So I’m way behind in the times (almost a week has gone by!), but I’m now adding I/O to my emulator. Notch has yet to officially publish any I/O specs, but there seems to be a de facto standard. Input is a 16-cell ring buffer at 0x9000 and video is 32x12 cells memory mapped at 0x8000 with characters and foreground/background colors encoded in the high byte. I’ll support everything from this spec (in 25 lines of F#!) except fonts and blinking; just using the standard console.


Input is easy enough. Just call this on every cycle:

open System

let mutable buf = 0
let input () =
let buffer = 0x9000
let size = 16
if Console.KeyAvailable then
b = buffer + buf
memory.[b] <- uint16 (Console.ReadKey
if memory.[b] = 13us then memory.[b] <- 10us // CR –> LF
memory.[buffer + size] <- uint16 (b)
buf <- (buf + 1) % size


Output too is pretty simple. The output function is called on every memory set:

let vidwidth, vidheight = 32, 12
Console.WindowWidth <- vidwidth
Console.WindowHeight <- vidheight
Console.Title <- "F# DCPU-16"

let output i =
    let vidmem = 0x8000
    if i >= vidmem && i <= vidmem + vidwidth * vidheight then
        let p = i - vidmem
        Console.SetCursorPosition(p % vidwidth, p / vidwidth)
        let v = int memory.[i]
        Console.BackgroundColor <- (v >>> 8) &&& 0x0f |> enum
        Console.ForegroundColor <- v >>> 12 |> enum
        Console.Write(v &&& 0x7f |> char)


I still have no assembler. I’m working on a Forth instead. For now just straight machine code (fun!):

let boot image = List.iteri (fun i c -> memory.[i] <- uint16 c) image; cycle ()

You could modify to load an image from a file and use with the DCPU Toolchain if you like. For a quick demo, let’s just take a couple of samples from the wonderful http://0x10co.de site:

// Screen test (see http://0x10co.de/y5096)
boot [0x7c01; 0xf030; 0x7c61; 0x8000; 0x7c0c; 0xf838; 0x7c03; 0xf000
      0x7c0c; 0x0a3a; 0x9c02; 0x00e1; 0x7c02; 0x0101; 0x8462; 0x19fe
      0x8010; 0x7dc1; 0x0004; 0x0020; 0x0000]


// Keyboard test (see http://0x10co.de/h6bbv)
boot [0x7c01; 0x8000; 0x8021; 0x8011; 0x4811; 0x0063; 0x781a; 0x0062 0x0481; 0x8402; 0x8422; 0x812d; 0x0063; 0x7dc1; 0x0004; 0x81ec 0x9010; 0x7dc1; 0x000f; 0x7c10; 0x0056; 0x7c81; 0x20df; 0x81ec 0x9010; 0x7dc1; 0x0015; 0x7821; 0x9010; 0x2811; 0x81e1; 0x9010 0x8021; 0x8121; 0x9000; 0x8422; 0xc02d; 0x7dc1; 0x0021; 0xa01c 0x7c10; 0x0037; 0xa81c; 0x7c10; 0x0044; 0x781a; 0x0062; 0x0481 0x8402; 0x7c0e; 0x817f; 0x7dc1; 0x000f; 0x7dc1; 0x0015; 0x7c81 0x0020; 0x7c0d; 0x8000; 0x8403; 0x788a; 0x0062; 0x7c8c; 0x2020 0x7dc1; 0x0037; 0x7dc1; 0x0015; 0x7c0e; 0x815f; 0x7dc1; 0x0015 0x7c81; 0xf000; 0x7c03; 0x8000; 0x7c02; 0x0020; 0x7c05; 0x0020 0x7c04; 0x0020; 0x7c02; 0x8000; 0x7dc1; 0x0015; 0x7c01; 0x8000 0x7c81; 0x0020; 0x8402; 0x7c0d; 0x8180; 0x7dc1; 0x0058; 0x7c01 0x8000; 0x61c1; 0x2000; 0x0054; 0x0079; 0x0070; 0x0065; 0x0020 0x0073; 0x006f; 0x006d; 0x0065; 0x0074; 0x0068; 0x0069; 0x006e 0x0067; 0x0021; 0x0000; 0x0000]


// Matrix Screen Saver (see http://0x10co.de/gpoke)
boot [0x7c51; 0x1234; 0x1441; 0x7dc1; 0x0009; 0x7c44; 0x274d; 0x8442
      0x61c1; 0x8061; 0x1031; 0x1441; 0x7c01; 0x8000; 0x8071; 0x7c10
      0x0005; 0x808c; 0x7dc1; 0x0024; 0x7c4f; 0x7000; 0x7dc1; 0x0024
      0x11a1; 0x0c41; 0x7c10; 0x0005; 0x7c89; 0xff00; 0x7c49; 0x003f
      0x508a; 0x0080; 0x1031; 0x6041; 0x8472; 0x8402; 0x1dfe; 0x0020
      0x7dc1; 0x000f; 0x8462; 0x1ace; 0x7dc1; 0x000e; 0x0c41; 0xb061
      0x7c01; 0x817f; 0x7c71; 0x0020; 0x808c; 0x7dc1; 0x004d; 0x7d0f
      0x0020; 0xffff; 0x7dc1; 0x004f; 0x7c10; 0x0005; 0x2101; 0x0020
      0x7d09; 0x0020; 0xff00; 0x1031; 0x7c39; 0x003f; 0x4d0a; 0x0020
      0x0080; 0x7c89; 0x7fff; 0x7dc1; 0x0052; 0x8101; 0x0020; 0x7d09
      0x0020; 0x7fff; 0x8473; 0x8403; 0x807e; 0x7dc1; 0x0034; 0x8463
      0x806e; 0x7dc1; 0x0032; 0x0c41; 0x7c01; 0x8000; 0x8071; 0x7c10
      0x0005; 0x7c4f; 0x0700; 0x7dc1; 0x0077; 0x7c8f; 0xffff; 0x7dc1
      0x0076; 0x7c81; 0x2000; 0x7c4f; 0x0800; 0x7c81; 0xa000; 0x1031
      0x7c39; 0x003f; 0x4c8a; 0x0080; 0x7dc1; 0x0077; 0x8081; 0x8472
      0x8402; 0x1dfe; 0x0020; 0x7dc1; 0x005f; 0x7dc1; 0x0009; 0x85c3
      0x0030; 0x0030; 0x0031; 0x0031; 0x0032; 0x0033; 0x0033; 0x0034
      0x0035; 0x0036; 0x0037; 0x0038; 0x0038; 0x0039; 0x0026; 0x007c
      0x007c; 0x0021; 0x0021; 0x0040; 0x003d; 0x003d; 0x003a; 0x003a
      0x002a; 0x002a; 0x0023; 0x0023; 0x003c; 0x003e; 0x003e; 0x005f
      0x005f; 0x0054; 0x0059; 0x0059; 0x0055; 0x0044; 0x0051; 0x005a
      0x004a; 0x004a; 0x0049; 0x0058; 0x002d; 0x0020; 0x007e; 0x007e
      0x006f; 0x0069; 0x0077; 0x006c; 0x0072; 0x006b; 0x006d; 0x002f
      0x002f; 0x005c; 0x0027; 0x005b; 0x005d; 0x005e; 0x0029; 0x0060]


// Psychedelic Screensaver (see http://0x10co.de/4r80g)
boot [0x7801; 0x002c; 0x7c10; 0x0025; 0x01e1; 0x002c; 0x0011; 0x7c16
      0x004f; 0x7c12; 0x0021; 0x7801; 0x002d; 0x7c10; 0x0025; 0x01e1
      0x002d; 0x7c09; 0xf000; 0x001a; 0x7801; 0x002e; 0x7c10; 0x0025
      0x01e1; 0x002e; 0x7c06; 0x0180; 0x0501; 0x8000; 0x8071; 0x8472
      0x1f4e; 0x7dc1; 0x001f; 0x7dc1; 0x0000; 0x19a1; 0x0061; 0x1864
      0x946a; 0x1802; 0x6061; 0x61c1; 0x3241; 0x3432; 0x2837; 0x0000]


Pretty fun stuff!