Recently a friend reached out to me with a clean dump of a particularly obscure arcade game, Contra: Evolution. Released originally for mobile phones back in 2010, it was a Chinese exclusive title. It eventually made its way to the arcade in 2011, and finally Android and iOS in 2013. I decided to take a look at it, and see if I could get it running through device emulation (instead of patching the binaries).

Initial Dive

The dump contained a raw hard drive image of the game, along with several photos of the original PCB. Checking the files that the game contained, it was pretty evident that this was a standard ACIO1 based game that didn’t employ the newer protection methods favored by Konami.

PS D:\KC1> ls

    Directory: D:\KC1

Mode                 LastWriteTime         Length Name
----                 -------------         ------ ----
d-----        2011-01-03   5:07 PM                copyright
d-----        2011-01-03   5:07 PM                data
-a----        2011-01-18   2:04 AM        1761280 AMContra.exe
-a----        2010-12-07   2:52 AM        4178264 D3DX9_41.dll
-a----        2010-12-07   3:19 AM          94208 libacio.dll
-a----        2010-12-07   2:51 AM         249856 libavs-win32-ea3.dll
-a----        2010-12-07   3:18 AM         385024 libavs-win32.dll
-a----        2010-12-07   3:19 AM          34345 path.lst

The older games that had exes available were typically protected with htpec, however, a quick check with Dependencies reveals that the import table is intact, so it’s likely unprotected.

DependenciesGui

A quick glance at the exports of AMContra.exe revealed that it was a pretty normal game, with 2 IO devices (HBHI2 and ICCA3) being referenced. Some weird things that I noticed were that libavs-win32-ea3.dll is never imported, even though it’s included, and there were some odd exports in libacio.dll (GfAcio/GfEvent) which I ignored for the time being.

With this information in mind, I wrote up a quick hook to emulate the ACIO bus and put 1 emulated device (HBHI) on it. This is because even though the ICCA handlers are imported, the game has a flag to disable the usage of it (is_disable_icca is always set to true).

device_mask = 0x22;
if (is_disable_icca) {
    device_mask = 0x20;
}
if (!ac_io_begin(2, "1.15.0", ctx.handler, device_mask)) {
    set_error(2, 1000);
    goto ERR_EXIT;
}

After writing up a quick test harness to inject the hook into the application, I started it up, and:

Contra PCB Error

Up to this point, I had only lightly skimmed the included libacio.dll, I had assumed that it was standard libacio, and had used a previously annotated database I had created on a newer version for it. This assumption was incorrect, and upon digging into the actual library included with the game, it was clear what we were dealing with was not in fact ACIO, but something else entirely.

P3IO or P4IO

After digging into the IO library some more, I ran some code that opened the interface at path \\p3io on some device, which initially lead me to believe that the device was a P3IO4, but after porting over the existing P3IO emulation that I had, I ran it and it promptly crashed.

Looking into it further, I finally noticed the numerous references to GfPython4 and took a look at the device GUID that it was looking for, it was really looking for a P4IO5. With the P4IO emulation instead, it got further according to some debug logging from my hooks but still resulted in the same PCB error as before. After making a small adjustment to the emulation code to mount the expected interface on \\p3io instead of \\p4io, we were in business.

Contra Security Error

Taking a brief moment to recap: what this game is using as its IO board is a P4IO, that names itself \\p3io, that has a shim libacio that makes it pretend to be an HBHI device node.

WTF.

At this point, I made the assumption that the security error was due to the game expecting security plugs to be attached to the P4IO, as there were numerous functions relating to this being imported by the game from libacio. After a brief interlude to port over the previous work for that, I booted it up again, and it continued to fail. It was at this point that I finally actually checked the export table of libacio:

...
34	10003F80	ac_io_begin_get_status(int)
53	10003F80	ac_io_hbhi_req_secplug_check(char const *)
55	10003F80	ac_io_hbhi_req_secplug_check_softwareplug(char const *)
56	10003F80	ac_io_hbhi_req_secplug_check_systemplug(void)
...

Notice that several functions have the same address? Here’s the code at that address:

char ac_io_hbhi_req_secplug_check() {
  return 1;
}

All of the security plug functions (among several others) were stubbed to do absolutely nothing. So wtf was going on now?

Cross-referencing some likely related phrases, I stumbled upon the string "security OK!\n". After looking into the function that referenced it a bit, I realized that indeed, the security plugs had nothing to do with the security. Instead, the game used some sort of check against files stored on the original drive to check for security. Bypassing this is trivial if the binary is patched, but to emulate it instead, we need to know what it’s checking (hint: it’s the MAC address). Emulating this is out of the scope of this blog post, but suffice to say, after implementing this we get to here finally:

Contra Clock Error

The game has built-in keyboard mappings (F1 - Test button, WASD, UJK for Player 1), and with these, it’s trivial to get into the test menu and see the IO page and guess the bits on the Jamma harness.

Contra IO Test

After that, the game runs perfectly.

Contra Game

Additional Mysteries

So reflecting on this game, several questions come up:

  • Why does it have card reader support if it’s hard-coded to be disabled?
  • Why does it use libacio, if it’s just going to shim the interface?
  • Why does the game reference GQIBBJAA in some secplug checking code if the model is GXKC1CAA6?

All of these questions can be answered by asking 1 question: what is IBB?

IBB is the model code for the game The★BishiBashi, which used an HBHI as its main IO board, and had a card reader. What likely happened was that some code was shared between The★BishiBashi and Contra: Evolution, and when they originally wrote the game it did use proper ACIO. However, at some point in development, they seemingly switched the design to use a P4IO instead and decided it was easiest to just shim the IO DLL, instead of rewriting the whole game. All known dumps of the game feature the same libacio shim.

One final question that comes to mind is, could these games or machines be bootleg? A cursory search on eBay shows several PCBs for the game for sale, all of them aside from one feature the P4IO, the one that doesn’t is clearly a clone / bootleg. This fact, coupled with the fact that in order to write the P4IO libacio shim, it would’ve required much greater effort and technical knowledge than someone outside of the original developers (as a bootleg could just use the built in keyboard support instead). Hence I would wager a guess that the game is not a bootleg, and did indeed release with a P4IO.

Final Thoughts

Overall I think that the most intriguing thing about Contra: Evolution is its IO, and supposed lineage (as a descendant of The★BishiBashi). These aside, the game itself is your standard fair “HD” remake of a classic that for whatever reason was never released outside of Japan.

I had an interesting time figuring out how to emulate the game’s hardware, especially with the confusing shim library that is used, and hopefully, this post was an enjoyable read!


  1. ACIO is a common serial protocol used by a variety of Konami arcade games, with the acronym probably standing for ArCade Input Output. 

  2. HBHI was a relatively unknown board to me at the time, but after some digging, it’s used as the IO node for several other games including Steel Chronicle, and HELLO! POP’N MUSIC. 

  3. ICCA (or ICCB/ICCC) are the card reader / keypad nodes used by Konami that speak ACIO. They’re pretty ubiquitous across Konami games. 

  4. P3IO or Python 3 IO, is the IO board found in a few games including DDR SD cabinets, as well as DDR X HD cabinets. It does NOT speak ACIO, and instead is a USB device, but has IOCtl’s to passthrough a serial port on itself. 

  5. P4IO or Python 4 IO, is the IO board found in a few games including DDR White HD cabinets and Gitadora. It does NOT speak ACIO either. 

  6. Model codes for games follow a typically standard pattern, GQ, followed by the game model (IBB or KC1 in this case), followed by the region (JAA or CAA in this case). This particular game has a GX prefix instead, as the model code was visible in one of the photos I was sent alongside the dump.