Skip to content

Instantly share code, notes, and snippets.

@JohnEarnest
Created October 31, 2019 01:56
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save JohnEarnest/0c52e244d34120ca32728a42e90ee169 to your computer and use it in GitHub Desktop.
Save JohnEarnest/0c52e244d34120ca32728a42e90ee169 to your computer and use it in GitHub Desktop.
XO-Chip Event Queue Proposal

Input Events

The COSMAC VIP had a 16-key hexadecimal keypad, and while modern computers rarely have a keyboard which directly mimics this arrangement, there are many approaches for adapting the input devices which are available to render Chip8 games playable. Many emulators offer custom keyboard or gamepad mappings for each program, and recently Octo has begun to offer "Adaptive Input" options to allow touch-based devices to play games.

It is often desirable to more directly expose the input capabilities of modern machines. This proposal outlines a pair of new instructions for XO-Chip which would expand it with text and pointer input, with room for future expansion. The instructions are as follows:

8NN8 #  v0 := poll NN
8XY9 #  event vx - vy

As input events occur, the XO-Chip interpreter will store them in a FIFO queue. The poll instruction pops events from this queue, storing the type code of the event in the fixed register v0. A type code of zero indicates that no events are currently available. Valid type codes each consist of a single set bit. The mask NN allows a programmer to indicate which events they are interested in; events will be drawn from the queue only if their typecode corresponds to a set bit in the mask. Consider, for example, a trivial loop which reads and discards any available events, halting when the queue is empty:

: drain
	loop
		v0 := poll 0xFF
		while v0
	again

Event codes correspond to one of the following constants. Each event type will be described in detail later:

OCTO_EVENT_NONE 0
OCTO_EVENT_CHAR 1
OCTO_EVENT_POINTER_DOWN 2
OCTO_EVENT_POINTER_DRAG 4
OCTO_EVENT_POINTER_UP   8
OCTO_EVENT_POINTERS { 2 | 4 | 8 }

Once an event has been selected via poll, the event instruction can be used to unpack the arguments for the event (if any) into the specified range of registers from vx to vy. If fewer arguments are available than there are registers given (or the current event is type 0 for "no event"), excess registers will be filled with zeroes.

Char Events

Char events correspond to characters typed on a keyboard. This event will always have a single argument, consisting of a 7-bit ASCII character.

Pointer Events

Pointer events unify a subset of the capabilities of mice, pen input, and multitouch input. An event fires when the pointer becomes active, as it is moved across the surface of the display or touchpad, and when it is lifted. These events all provide two arguments- the horizontal (X) and vertical (Y) position of the pointer relative to the screen, respectively, in pixels. Like the Chip8 drawing coordinate system, X coordinates count left-to-right from 0, and Y coordinates count top-to-bottom, from 0. The following example tracks the pointer with a sprite while it is active:

: main
	i := hex v0
	loop
		# service events
		if v3 != 0 then sprite v1 v2 5
		loop
			v0 := poll OCTO_EVENT_POINTERS
			while v0
			event v1 - v2
			v3 := 0
			if v3 != OCTO_EVENT_POINTER_UP then v3 := 1
		again
		if v3 != 0 then sprite v1 v2 5

		# sync framerate			
		loop
			vf := delay
			if vf != 0 then
		again
		vf := 2
		delay := vf
	again

Pros and Cons

This proposal would substantially expand the options available to XO-Chip programmers for offering natural and flexible input capabilities on a broad range of devices. The event types, and their arguments, avoid tying programs to designs which would be limited to desktop computers or mobile devices, or complex device-dependent encoding systems. The event masking system makes it easy to write programs which ignore input they are uninterested in, and which are robust to the introduction of new event types in the future. The ranges of input codes and argument counts afforded by the instruction encoding likewise leave generous room for future expansion, should it prove necessary.

There are some risks or limitations to this design. The instruction encoding is forced to use the 8 prefix which is normally associated with arithmetic instructions, and which could be confusing to implementers. The mask nybbles of poll are positioned across both bytes of the instruction, which breaks from convention with existing instructions and could make self-modifying code which modifies this field more difficult than necessary. Explicit events for keyboard key up/key down events are avoided as these can already be supported to some extent via normal Chip8 key input facilities. More importantly, representing arbitrary keyboards via scancodes in a portable fashion is a challenging specification problem which is best avoided entirely.

@JohnEarnest
Copy link
Author

Using vF instead of v0 for poll is a possibility. XO-Chip has indeed relaxed the constraints that forced the preference for low registers for temporary work.

Most of the questions of how I handle encoding the new instructions aren't a big deal; I just felt they were worth mentioning as considerations.

I do forsee that the addition of these instructions would effectively divide programs into two styles: "keyboard and mouse" programs using the new mechanism and "gamepad" programs which continue to make use of the VIP input controls. The only downside to this, in my opinion, is that "keyboard and mouse" programs would probably not be adaptable to some of the esoteric/homebrew hardware platforms that CHIP-8 has been ported to, like the ESPBoy. So far, though, XO-Chip hasn't really seen adoption by third party emulator authors anyway.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment