Skip to content
Hacking the My Arcade Contra Pocket Player - Part I

Hacking the My Arcade Contra Pocket Player - Part I

December 9, 2021

Intro

The other day I was walking through Target and noticed they had a bunch of collectable arcade systems available. They had everything from Pac-Man and Galaga to Contra. Some were full size standing cabinets (about 4 feet tall), while others were handheld versions. I picked up a few different handhelds to take a look at and most appeared to be your run-of-the-mill NES-on-a-chip Famiclone systems, which wouldn’t be super interesting for ROM swapping since they tend to have the games hard-coded onto the chip.

Target Arcade Games and Handhelds
Figure 1 -- Target Arcade Games and Handhelds

As I was looking over the options, this Contra handheld caught my attention for a few reasons. First, the box advertised a feature called “CO/VS Technology” which claims to allow two systems to connect together for multiplayer. Second, the system had a tall screen that more closely matched the proportions of the arcade version rather than the standard 4:3 that I would expect from a typical Famiclone. I ended up picking up a couple of the handhelds to take a closer look.

My Arcade Contra Pocket Player
Figure 2 -- My Arcade Contra Pocket Player

Teardown

Inside the game console, there are multiple components of interest.

Pocket Player Teardown
Figure 3 -- Pocket Player Teardown

The main SoC is a Rockchip RK3128, which is a quad-core Cortex-A7 with a Mali400 MP2 GPU. The system also has 2Gbit of DDR3 RAM and 1Gbit of storage via a Winbond serial NAND flash connected over an SPI interface. Additionally, there is a micro-USB port, an audio port, and a port for the CO/VS multiplayer connector.

Hardware Probing

My first attempt at getting data off of the system was to try and dump the flash. I hooked up my HydraBus (you could also use a Bus Pirate) and attempted to use flashrom to dump the data. Unfortunately, flashrom is typically used to operate on SPI NOR flash, but the Winbond W25N01GVZEIG is a NAND flash. So, we will need to read the NAND flash datasheet and write some commands manually.

After reviewing the block diagram from the datasheet, we learn the following:

NAND Flash Block Diagram
Figure 4 -- NAND Flash Block Diagram

  • The flash is organized by blocks
  • Blocks consist of 64 pages
  • A page consists of 2,112 bytes of data
    • 2,048 bytes of actual data
    • 64 bytes reserved for ECC data
  • A column address is used to index into the page to read specific bytes

To dump all of the data, we would need to load the first page, set our column address to 0, start reading data from the page, increment the column address, and repeat through all available pages.

Let’s check the pinout to see how we should hook this up to the HydraBus.

NAND Flash Pinout
Figure 5 -- NAND Flash Pinout

The SPI interface is fairly straightforward, so let’s go ahead and hook it up. I’m using PCBite probes here to avoid having to solder any wires to the chip.

Probing the NAND Flash
Figure 6 -- Probing the NAND Flash

To test our connection, let’s start with the Read JEDEC ID instruction. According to the datasheet, this will return 3 bytes that identify the manufacturer and device.

Read JEDEC ID Command
Figure 7 -- Read JEDEC ID Command

We need to send 0x9F followed by 8 dummy clocks and then read 3 bytes. Using the HydraBus, we can do this by entering into SPI mode and using the following command:

[ 0x9F 0x11 r:3 ]

Let’s break down the command to see what we are doing here:

CommandDescription
[Chip Select (CS) enable (active when pin is low)
0x9FSend the Read JEDEC ID command
0x11Dummy byte to fill 8 clock cycles (can be any byte like 0x00)
r:3Read the next 3 bytes sent from the NAND flash (this is our JEDEC ID)
]Chip Select (CS) disable (inactive when pin is high)

Reading the JEDEC ID
Figure 8 -- Reading the JEDEC ID

We get back 0xEF 0xAA 0x21. Let’s compare this to what we expect from the datasheet.

JEDEC ID Listed in NAND Flash Datasheet
Figure 9 -- JEDEC ID Listed in NAND Flash Datasheet

We got the expected result, so we should be good to start dumping data.

Dumping the Flash….Maybe…

[ 0x03 0x00 0x00 0x00 r:255 ]

Let’s break down the command again:

CommandDescription
[Chip Select (CS) enable (active when pin is low)
0x03Read the data command
0x00Column Address CA[15:8]
0x00Column Address CA[7:0]
0x00Dummy byte to fill 8 clock cycles
r:255Read the next 255 bytes sent from the NAND flash
]Chip Select (CS) disable (inactive when pin is high)

Attempted Data Dump
Figure 10 -- Attempted Data Dump

At first glance, the data seems like it could be good, but after performing multiple reads from the same location, the data being returned was different every time. This meant that we would not be able to assemble an accurate dump of the flash.

I wasn’t sure if the issue was related to reading the NAND flash in-circuit or a configuration issue with the HydraBus. I considered breaking out a logic analyzer or oscilloscope to take a closer look, but before doing that, I found a much better way to get the data.

RTFM - USB Recovery

After doing some Google searching on the RK3128 SoC, I found that it is commonly used in Android devices and TV boxes. Looking into the Rockchip wiki, I found that many Rockchip devices support a USB recovery mode that can be triggered by holding the volume up key while powering on the device via USB.

RockUSB Recovery Mode
Figure 11 -- RockUSB Recovery Mode

Sure enough, powering on the device while holding the volume up button caused it to be detected as a RockUSB device in Mask ROM mode.

Detected RockUSB Device
Figure 12 -- Detected RockUSB Device

NAND Dump

Using rkflashtool, which speaks the RockUSB protocol, we can dump the NAND flash. The tool expects an offset and size in blocks of 512 bytes.

If we go back to the NAND datasheet, we can see that it contains 65,536 pages of data with 2,048 bytes per page for a total of 134,217,728 bytes of data. Dividing this by the 512 byte sector size gives us 262,144 total sectors. So, we can dump from sector 0 to 262,144.

sudo ./rkflashtool r 0 262144 > ~/Desktop/nand_dumps/nand_dump.bin

I recommend doing 1-2 additional dumps and comparing file hashes to ensure you got a good dump.

Comparing NAND Dump Hashes
Figure 13 -- Comparing NAND Dump Hashes

Our hashes match! Opening the dump in a hex editor, we can see a GUID Partition Table header.

GUID Partition Table Header
Figure 14 -- GUID Partition Table Header

Digging further into the dump, we can find a reference to the Contra ROM and what appears to be a MAME arcade emulator.

Contra MAME ROM File
Figure 15 -- Contra MAME ROM File

Part 2 Sneak Peek…

Stay tuned for Part II of this post, where we will dig into the NAND image, swap out the ROMs, and see what else we’re able to get running on this thing!

Sneak peek


This post originally written for TrustedSec and posted here with permission.