❀°。Deijin's Blog

Reverse Engineering Pokédex 3D Pro AR Markers

This post covers my process of figuring out how the AR markers used in Pokedex 3D Pro are generated.

The Discovery Process

One day in 2020 I spotted my old pokemon national pokedex book I got when Black and White came out.

Photograph of black and white national pokedex book front cover

I decided to take a look through it. Something funny I spotted was where I had corrected the stat bars of certain pokemon using pens. Persian, for example, had its special attack and speed the wrong way around. I'm amazed that they must literally have manually made the stat bars for every pokemon for this to have happened.

Photograph of national pokedex book open on the page of persian, vertical blue and red lines reperesent base stats, and these have been modified using felt tip pens

But there was something else I saw. Each generation 5 pokemon had a scannable marker. I whipped out my 3DS and booted up pokedex 3D pro, and in front of me emerged a pokemon. Revolutionary!

image 3ds screen which is live superimposing a 3d model of victini above its marker on the page of the book

I started to wonder how the codes were actually made. From the very start I was sure that it must somehow derive from their pokedex numbers; the reason being that the pokemon near eachother tended to have more similar markers.

Photo of the ar markers of tepig, pignite, and emboar, which have similar shapes

I wrote out the pixels of a few of them in a various reading orders as bits and tried converting them to a number to no avail. There must be something more tricksy going on. I wrote out a good bunch of them at noticed some patterns. Bit-C consistently alternated between 1 and 0. Bit-F alternated every other time. So the numbers were progressing, but the bits were shuffled up.

0123 4567 89AB CDEF
1111 1001 0100 1110 494 victini
1111 1001 0100 0111 495 snivy
0111 1001 0100 1111 496 servine
1110 1001 0101 0010 497 serperior
0110 1001 0101 1010 498 tepig
0110 1001 0101 0011 499 pignite
1110 1001 0101 1011 500 emboar
0111 1001 0101 0010 501 oshawott
1111 1001 0101 1010 502 dewott
1111 1001 0101 0011 503 samurott
0111 1001 0101 1011 504 patrat
1110 0001 0101 0110 505 watchog
0110 0001 0101 1110 506 lillipup
0110 0001 0101 0111 507 herdier
1110 0001 0101 1111 508 stoutland
0111 0001 0101 0110 509 purrloin
1111 0001 0101 1110 510 liepard
1111 0001 0101 0111 511 pansage
0111 0001 0101 1111 512 simisage
1000 1100 1110 0000 513 pansear
0000 1100 1110 1000 514 simisear

Bits I had figured out so far

X X X 2
X X X X
X X X 4
0 3 X 1

From this, the known bottom few bits compared to the bottom few bits of the national pokedex numbers (left is the calculated bits, right is the bits in the national dex number):

01101 01110 494 victini
01110 01111 495 snivy
01111 10000 496 servine
10000 10001 497 serperior

It had become clear that the ar marker is generated from the national dex number minus 1.

For the larger, less frequently alternating bits I was going to have to jump to the "turning points" to save time. That is, where a bit changes from 0 to 1 or 1 to 0.

Turning points for bits:

5: 31-32
6: 63-64
7: 127-128
8: 255-256
9: 511-512

I could find the ar markers on the pokedex 3D pro app for these lower ids, and going through the turning points low to high I could one by one figure out which pixel corresponds to which bit.

Interestingly enough, there seems to be two pixels mapping to the ninth bit.

A 8 5 2
B 9 E 7
C D 9 4
0 3 6 1

Would you look at that, it makes a spinny pattern!

D and E are always 1 and 0 respectively. You could suggest that the 0 one is just the 10th bit, but ultimately it doesn't matter, the pokemon ids never get high enough for that to matter.

Anyway, what on earth is going on with A, B and C? I looked down the sequence and they seem to just cyclically loop through a set of values. And yes, that set of values is indeed the bits of the funny number.

0110 1001 = 0x69

Nice! Honestly, this is probably just a complete coincidence, but I like to think that the creators had a sense of humour.

Summary

The markers are derived from an id which is just the pokedex number of the pokemon minus 1. The alternate forms of pokemon are listed after the main pokedex.

The 0-9th bit in the id map to pixels as follows (bit 9 appears in two pixels):

A 8 5 2
B 9 E 7
C D 9 4
0 3 6 1

Pixel D is always white, and E is always black.

A, B and C are created by cycling the bits of 0x69.

Code Implementation

ArMarkerViewer - Application to view all valid AR markers.

See specifically this page for the code to generate a marker from an id.

Interesting Observations

Now that I had code to generate these markers, I could scan codes above the highest pokemon, and I found some interesting things.

For ids 988-999, they "mirror" a recently loaded ar marker. That is, if you scan a bulbasaur code then scan one of these it will show a bulbasaur too.

For ids 1000-1011, they choose a random pokemon to display.

I have no idea why this unusual behaviour exists.

#pokemon #programming