With a working emulator and interface developed over the previous five parts, the emulation system is able to run a basic test ROM, and produce graphical output. What the emulator is currently unable to do is take keypresses as keypad input, and feed them through to the ROM under test; in order for this to be done, the keypad's influence on the I/O registers must be emulated.
With the addition of keypad I/O, the emulator runs as follows.
The GameBoy has a single method of input, an eight-key pad out of which any number of keys can be depressed. With most keyboards, the keys are laid out in a grid of columns and rows: these can be treated as wires, between which a key can form a connection. When one of the columns is activated, any rows connected to that column will also activate, and the hardware is able to detect the active rows to determine the currently pressed keys.
With the GameBoy, the keyboard grid has two columns and four rows, which has the advantage that all the required connections can be made within one 8-bit I/O register.
Since all six lines are tied to the same register, the GameBoy procedure for reading a key is slightly convoluted:
- Write either 0x10 or 0x20 to JOYP: this will activate either bit 4 or 5, one of the column lines;
- Wait a few cycles for the row connections to propagate to JOYP;
- Check the low four bits of JOYP, to find which rows were active for this column.
Implementation of the keypad
keyup events can be used to find out when a key has been pressed or released; tying these into the keypad handler can be done in the following manner.
Key.js: Object interface
In addition to this, the MMU must be extended to handle the keypad I/O register, with an addition to the zero-page handling routines; an example of this is given below.
MMU.js: Keypad I/O interface
event object; any event that runs through the browser, such as a mouse click or a keypress, will be passed to the code if it's requested, along with an object that describes the event that's just occurred. In the case of a keypress, the
event object contains a character code and a "key scan" code, which both describe the key in question.
keydown events; in any browser, pressing a given key will yield a particular value.
For the purposes of this emulator, eight keys need to be handled by the keypad code:
As stated above, the appropriate bits must be reset when a key is pressed, and set when the key is released. This can be implemented as follows.
Key.js: Keypress handling
Testing and next steps
Figure 1 above shows the result of these additions to the emulator, when running a basic tic-tac-toe game. In this example, the initial screen can be advanced to the credits by pressing the Start key, which is mapped to Enter by this emulator. Another press of the Start key will bring up the game screen, and the game can be played with the player as one side, and the computer as the other; pressing the GameBoy's A key (mapped to Z) will place a cross or circle on behalf of the player.
Imran Nazar <email@example.com>, Sep 2010.
Article dated: 19th Sep 2010