Jump to content
Kev

chip8c

Recommended Posts

chip8c

As an alternative to an emulator, this tool translates CHIP-8 binaries into equivalent C code, which can be compiled on POSIX-compliant OSes with ncurses.

This is just a proof of concept, and the way it works could be still improved (see Details).

 

Usage

Compiling the tool:

make

 

Translating a CHIP-8 binary:

./chip8c breakout.ch8

 

 

Running the above will produce 3 files:

  1. mem.h - memory map of the binary
  2. breakout.ch8.c - translated C
  3. breakout.ch8.bin - runnable binary

 

CHIP-8 has its own keyboard layout. To interact with the binary, use mapped keys:

1 2 3 C --mapped as--> 1 2 3 4
4 5 6 D                Q W E R
7 8 9 E                A S D F
A 0 B F                Z X C V

 

Some CHIP-8 executables can be found on repos like this one. The ones that were tested and work well include pong, breakout and trip8 demo.

 

Details
What the tool was created for, is to check whether it's feasible to decompile machine code into a long switch-case, where the switched value is the program counter register, and the cases are instruction addresses coupled with code performing register and IO manipulation equivalent to that of a given instruction set.

 

Insides of the resulting switch-case look like the following example:

switch (pc) {
/* ... */
case 0x0200: reg[0] = reg[6];
case 0x0202: reg[1] = 0xFC;
case 0x0204: reg[0] &= reg[1];
case 0x0206: regi = 0x30C;
/* ... */
case 0x0242: reg[0] = 0xFE;
case 0x0244: reg[9] ^= reg[0];
case 0x0246: stack[sp++] = 0x0246 + 2; pc = 0x2A4; break;
case 0x0248: reg[5] += 0x01;
case 0x024A: stack[sp++] = 0x024A + 2; pc = 0x2A4; break;
case 0x024C: if (reg[5] != 0x60) { pc = 0x024C + 4; break; }
/* ...*/
}

 

Worth noting, that breaking out from the switch-case is required only when jumps are performed, in all other cases it suffices to allow for the default linear flow.

 

There are a few disadvantages of the technique:

  1. Code gets separated from data, so whatever takes advantage of von Neumann architecture won't work.
  2. A hexdump of a translated binary must be included in the resulting C file, so it could access its static data.
  3. Jumps to unexpected addresses aren't handled (odd addresses, for instance).

 

This implementation uses ncurses for IO, which was chosen for its popularity and simplicity, but it's not a good fit for mimicking IO of CHIP-8. For instance, the instructions EX9E and EXA1 work best if the program maintains a map of keys that are currently pressed. It seems that ncurses doesn't detect key releases, so its hard to maintain such a map.

 

Also, it would be nice if Unicode block characters could be used for the output, then neighbouring pairs of pixels could be packed into one of:  , ▀, ▄ and █ to simulate nice looking square pixels.

 

Download: chip8c-main.zip

 

or

 

git clone https://github.com/kiryk/chip8c.git

 

Source

 

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.



×
×
  • Create New...