Wishful Coding

Didn't you ever wish your
computer understood you?

Connect SPI sensors to a Game Boy

In all my previous Game Boy hardware hacks, I always used an Arduino to talk to the Game Boy over the Game Link cable. But the Game Link protocol is essentially just SPI, so I was thinking it would be trivial to talk directly to SPI sensors.

So I ordered an LIS3DH breakout from Adafruit and connected it to the Game Link port of my Game Boy. I wrote some code to read the WHOAMI register of the sensor, which should return 0x33. Nothing happened. I double-checked all the code and wiring, but nothing worked.

On day two I probed around with my oscilloscope and dug around in the datasheet. The problem turned out to be that I tied the Chip Select to ground, which is actually required to indicate the start of a transaction1. But the Game Boy does not have a Chip Select pin, so that seemed like it would be the end of it.

On day three I figured I might be able to emulate the CS line somehow. I tried various things with low-pass filters, binary counters and even an Attiny25, but nothing quite worked. The highlight of the day was that the Game Boy would display 0x24 if the stars aligned, and random junk otherwise. I gave up again.

On day four I woke up with the winning solution. It was glorious.

33

A MOSFET buffer connected to the clock line pulls low the CS line and a capacitor combined with the 10k pull-up on the breakout keep the line low between clock pulses and release it after transmission.

33

I have never before been so excited about the number 0x33. After 4 days of despair, trial and error, it finally worked.

33

It should be noted a large delay between transactions is required to raise the CS pin, so transmission will be slow.

After setting up the control registers somewhat correctly, I was able to read accelerometer data from the sensor. I made a quick demo that moves a dot around by rotating the sensor, as seen in the video. It’s not hard to imagine you could easily make a tilting maze game out of this.

But I have other plans. To be continued.

  1. I checked various sensors, and every single accelerometer I found was dual I2C/SPI and bit-for-bit identical to the LIS3DH, so using another sensor was not an option. 

Does a compiler use all x86 instructions?

On the Z80 CPU there are so few registers and instructions that you can easily know and use them all and wish there were more of them. However, half of the time it feels like the only on you really use is ld. I imagine that if ld took half the number of clock cycles, average code would run twice as fast.

In modern x86(_64) there are so many that I even wonder if my compiler knows and uses them all, and how often. To get an impression, I ran this one-liner:

objdump -d /usr/bin/* | cut -f3 | grep -oE "^[a-z]+" | sort | uniq -c

Full output here. In total I counted 411 different mnemonics, topped by 15891451 mov instructions and a very long tail of instructions that only occur once or twice.

There are 33% mov instructions. Combined with callq, je, and lea making up over half of all code.

Opcode pie chart

Between the expected compare and jump instructions, “Load Effective Address”, “eXclusive OR” and “No OPeration” surprised me. Of course nop is probably padding and xor is the best way to zero a register, but I have no clue why there are so many lea everywhere.

Nobody really seems to know how many x86 instructions there are, but someone counted 678, meaning there are over 200 instructions that do not occur even once in all the code in my /usr/bin.

It would be interesting to break it down further in “normal” instructions, SIMD instructions, other optimizations, and special purpose instructions… if anyone can be bothered categorizing 600+ instructions.

Published on

Game Boy Paint

After my various Pokemon hacks and reading portions of the Pokemon Red source code, it occured to me it would be fun to write my own game from scratch. But in typical fashion I got sidetracked thinking about the engine, levels, sounds and graphics.

I decided that “obviously” the best thing to do was to write editors for the game first, starting with the paint program.

I did most of this away from the internet, giving a more authentic feeling of having just the assembler between you and the machine and just the manual to guide you. (I did ocasioanlly visit #pret for advice)

I could not find much in terms of complete tutorials. I bascially relied on 4 major resources.

  • pandoc lots of info about the hardware
  • CPU manual all the details about the instruction set
  • GALP sample code and hardware defines
  • pokered large corpus of working code and tooling to steal and learn from

I figured I would dedicate one tile set entirely to the canvas and the other on to the UI. I’d use the background tiles for the canvas, the window tiles for the UI and the sprites for the cursor.

Until I found the window layer is opaque and shares the same tile set as the background. It even turns out the two tile sets partially overlap, giving me only half a tile set for the UI.

In the end I did not use the window layer, but switched the tile set used by the background during hblank, so that the top half of the background is drawn using the first tile set and the bottom with the other set. A few hundred lines of assembly later…

gbg screenshot

With the UI basically working I started actually drawing tiles. This involves finding the correct tile, the correct row in that tile, and then flipping two bits in the 2 bytes comprising that row. Dozens of lines of assembly later…

gbg screenshot

Drawing bigger lines is a matter of flipping more bits. To do this I defined a pattern like %11110000 that I would roll to the correct position and and with the tile. This does kind of break when you draw a big brush past a tile edge, but that’s a problem for later.

gbg screenshot

This is what I love about assembly game development. Instead of a nice error message you get this glorious glitch on your screen and you have no idea what you did wrong.

The Game Boy has this weird two bits per pixel format where all significant bit for a pixel are in byte one and the least significant bit for the pixel is in the second byte. The loop that was supposed to fill a square with the selected color wasn’t exactly right.

gbg screenshot

Fixing that loop allowed me to draw in various colors and sizes, but large brushes still overflow to an adjacent tile.

gbg screenshot

I chose to self-align brushes, so your 2x2 brush moves with 2px increments and the 8x8 brush moves at 8px increments.

gbg screenshot

Finally, I implemented loading and saving to SRAM. With the aid of the pokered tools, a simple make export converts your saved tile set to a png, and with a bit of fiddling you can also convert a random flower picture to a tile set and paint your name on it.

gbg screenshot

Whew, that was harder than expected. It was challenging and fun and I learned a lot, but I’m not sure if I’ll write a full game this way. The full 700+ lines of assembly can be found here.

It was shocking to me to find how limited Z80 assembly is. There are only a hand full of registers, and a hand full of valid combinations. Many operations (math, literal load, address load) only work with a as the source/destination. 16-bit addition (together with inc the only 16-bit ops) only works with hl and the stack pointer.

It’s easy to see that in this environment, hand-written assembly outperforms C. With so few ops and registers, C is bound to push a lot of local variables to the stack, and unlikely to make efficient use of high-ram and registers. It’s also very easy to do things in C that have no hardware equivalent, such as multiplication/division and anything with signed or 16-bit numbers.

On the other hand it’s also easy to see that on modern platforms and large code bases, C beats assembly in every possible way. Maybe even on a Game Boy an indie(you know, for individual) game is more feasible using C, when used carefully.