How To: Latest 0x10c Screenshot Hints at How to Write to the In-Game Terminal from DCPU-16 Assembly Code

Latest 0x10c Screenshot Hints at How to Write to the In-Game Terminal from DCPU-16 Assembly Code

Latest 0x10c Screenshot Hints at How to Write to the In-Game Terminal from DCPU-16 Assembly Code

Update: Based on comments from Adam Novak, this article has been updated to better reflect how the video memory range works. You can check out his working emulator (written in c) here.

The latest screenshot of the (super early) build of 0x10c, still apparently under the name "SpaceGame", gives away a two new details about the DCPU-16's instruction set that everyone who's been building compilers has been wanting: 

  • A standard way to show output to the in-game terminal.
  • A way to store data that can be looped through.

Latest 0x10c Screenshot Hints at How to Write to the In-Game Terminal from DCPU-16 Assembly Code

Writing Text to the In-Game Terminal

It appears that std out to the terminal is performed by SETing the memory values in the 0x8000 - 0x8400 range (which gives you a 32x32 character grid) with one word per character using the lower 8 bits for text, & leaving room in the upper 8 bits for colors. I can't tell yet specifically what values correspond to what colors, other than 0x170 seems to be grey text on a dark gray (or perhaps the default black?) background.

Take a look at line 15 in the assembly code below and you can see how each character in the strings from the data subroutine end up getting set in sequence to 0x8000, 0x8001, 0x8002, etc.

Latest 0x10c Screenshot Hints at How to Write to the In-Game Terminal from DCPU-16 Assembly Code

Setting and Accessing Data Using the DAT Instruction

Incidentally, the "dat" instruction used to set the strings and colors on line 31 was documented in a pastebin linked to from notch's tumblr, though it's not documented in the DCPU-16 specification (as of version 1.1). The format seems to be a 0 terminated and comma separated sequence of data, including support for strings. So, each of the following appear to be valid:

  • dat "Hello World", 0
  • dat 0x170, "Hello ", 0x2e1, "World", 0
  • dat 0x170, 0x2e1, 0

Can any of you figure out how the values correspond to colors? From a quick glance, the color (stored in b) seems to be combined with the character to output (stored in a) before a's value is set to the proper 0x8000 address for the character to be displayed on the in-game terminal.

18 Comments

Given that the "SpaceGame" is written in Java, I would think that the colors would probably be fairly standard 16bit hex values... But given that assumption, I can't see how 0x170 would give you a shade of grey. I must be missing something...

What about another color representation, like a type of HSL or YUV, with lightness as the middle digit?

The format seems to be 1 word per character of video memory. The low 8 bits specify the character, and the high 8 bits specify the formatting (foreground and background color). The mapping could be something like standard ANSI colors, which use about a byte. We might get 16 foreground colors and 16 background colors, or slightly fewer and have blink or underline.

Hmmm. Seems like the 0x8000 block of video memory is a temporary solution while notch works on a more modular approach (thanks Andrew Kersten).

It's not an opcode, it's an instruction to the assembler to put a block of constant data in the binary. And it's not exactly new--it appeared in a pastebin linked from the original Tumblr post with the original CPU specs.

My assembler has support for it already (for just strings, unfortunately), and my emulator has (black and white) video memory implemented. See https://bitbucket.org/interfect/dcpu-emu/overview

"It's not an opcode, it's an instruction to the assembler to put a block of constant data in the binary." You took the words right out of my mouth.

Ah. That makes more sense. I'll update the post.

I translated this code into pseudo-C for y'all. I'm a little rusty, so I may have some incorrect pointer syntax.

*data = 0x170, "Hello ", 0x2E1, "world", 0x170, ", how are you?", 0;

start:

i = 0;
j = 0;
b = 0xF100;

while (a = *(data + i)) {
if (a 0xFF) {
b = (a & 0xFF) 0x1FF) {
b += 0x80;
}
} else {
a |= b;
*(0x8000 + j) = a;
i++;
j++;
}
}

goto start;

# b: color value, to be ORed with a
# grey on black: 0x7000
# yellow on blue: 0xE180

The variable types are all unsigned short int (on most systems) BTW.

No indentation!? To pastebin! http://pastebin.com/cTCJv8D5

Boo to that. I just added support for pasted tabs in comments :)

How about angle brackets? Ore maybe a code tag?

We're preparing to launch an entirely new version of the site. I'll invite you to the private beta test if you like... Message me if you're interested in helping us work the kinks out.

It looks like it's related to the ANSI color codes. 0x70 is grey on black (where grey = dark white), but yellow on blue is 0xBC. Note that the color codes are in the high bytes. It's also apparent that we're dealing with 7-bit ASCII, and that 8th bit is another flag.

I just don't understand why the program has to decode 0x170 into 0x7000, and 0x2E1 into 0xE180, except that it tests the emulator's and assembler's SHL, AND, and IFG instructions.

I figured out an explanation for the 0x170 -> 0x7000 thing. It gives us 256 data streams. Stream 0 is text and Streams 1 & 2 are color data. Stream 2 has that extra bit - add b, 0x80.

2 more streams could be used for cursor position. If there are multiple monitors, switching could be a stream. Anybody got ideas for more?

Perhaps more could be used for image / sprite manipulation (Notch mentioned he wants to build in "hardware" sprites so that the DCPU-16 can focus on simpler tasks).

Share Your Thoughts

  • Hot
  • Latest