Wishful Coding

Didn't you ever wish your computer understood you?

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.

Pepijn de Vos

Pokemon Gringo

In Puerto Rico, folk etymology states that the word “gringo” originated from the English words “green” and “go” referring to the desire of some locals to have the U.S. military (who allegedly wore green uniforms) leave the island by telling them: “Green, go!” 1

As a long-time Pokemon fan, I got really excited when I heard about Pokemon Go. But excitement quickly turned into disappointment as I found out the Android runtime on my Blackberry does not support the required API version.

So I took my Gameboy to play some good old Pokemon Red, when a thought struck me. How hard would it be to add a GPS to TCPoke and modify pokered to allow TCPoke to initiate wild Pokemon battles?

I had previously read parts of pokered to understand the serial protocol I needed to make TCPoke, but I never actually wrote Z80 assembly. Luckily, it turned out to be relatively easy. After a few hours I already added an extra menu item to the Cable Club, and a few hours later the menu actually did something.

It’s kind of glitchy and broken, but the diff is surprisingly small.

GBG simulation of Pokemon Gringo

Next up I modified Bill’s Arduino state machine to recognize the new menu item and added some GPS code. Again, it took a few hours, but the diff is again relatively small. (Except for this huge chunk of Pokemon level and location data I extracted from pokered)

But at this point I only had the code running in BGB/Gambatte (which I even modified to emulate BIll’s Arduino), so I had to order a flash cart to load the modified ROM onto my Gameboy. After camping on the doormat for a week, ignoring friends and family and only leaving the house outside delivery hours, today I finally received the cart and could begin testing on real hardware.

First boot

It almost worked on the first try! There were some small bugs in the Arduino code, which I could not test up to this point. Then I did a few rounds around the block, carrying my whole laptop+Teensy+Gameboy around for debugging. The first Pokemon I encountered made me almost jump into the air from excitement and surprise.

Pokemon Gringo really captures that feeling of surprise when you’re happily trodding along when suddenly…

GBG simulation of Pokemon Gringo

For the best experience I recommend turning up the volume all the way and physically walking though tall grass.

Here is a video of me walking to the supermarket with my new gear.

Pepijn de Vos

AVR pseudo-DMA

I’ve been thinking about making my own 8-bit retro hand-held console, not unlike a GameBoy Color. 8-bit microcontrollers and buttons are easy to come by, memory, sound and a display not so much.

The Atmega2560 used in the Arduino Mega has support for external memory, which is nice. This allows up to 64kb of RAM, and even more if you implement bank switching.

The display is an unsolved problem for me so far. Sure, there are dozens of display shields and breakouts, but pushing pixels over a serial bus with an AVR is just too slow. If you just make the Arduino sit in a busy loop sending bytes over SPI at top speed, it takes hundreds of milliseconds to update the whole screen.

The proper way to do it seems to be to have a framebuffer that you DMA to the screen controller, while the CPU is busy making the next frame. Except the only chips I found that support DMA can hardly be considered retro, and often not even 8-bit. We’re talking 32-bit, 100Mhz chips like AVR XMega, dsPIC or ARM Cortex-M3 here. While the GameBoy does all of that at 4Mhz. I’m not sure what kind of black magic that is.

In this moment of despair, I came up with a way to do something like DMA on the Arduino Mega. I figured that with a couple of diodes I could transfer data from a RAM chip to the screen.

Normally you’d connect both the RAM and the screen to the SPI lines and give them a chip-select line each. What I did is disconnect the MISO of the screen and connect the MISO of the RAM to the MOSI of the screen. This way, if you lower both CS lines and send a zero, a byte is transferred from the RAM to the screen.

Pseudo-DMA Schematic

The hack that makes this work combines code from Adafruit_ILI9341 and Adafruit_FRAM_SPI, which results in the following glorious disaster

void framDMA() {
  // set up the display
  spi_begin();
  tft.setAddrWindow(0, 0, ILI9341_TFTWIDTH-1, ILI9341_TFTHEIGHT-1);
  // set up the RAM
  digitalWrite(fram._cs, LOW);
  fram.SPItransfer(OPCODE_READ);
  fram.SPItransfer(0);
  fram.SPItransfer(0);

  digitalWrite(tft._dc, HIGH);
  digitalWrite(tft._cs, LOW);
  // at this point BOTH the display and FRAM are active
  // Send zero's
  for(int i=0; i<ILI9341_TFTWIDTH; i++) {
    for(int j=0; j<ILI9341_TFTHEIGHT; j++) {
      SPDR = 0;
      while(!(SPSR & _BV(SPIF)));
      SPDR = 0;
      while(!(SPSR & _BV(SPIF)));
    }
  }
  // release the cs lines
  digitalWrite(tft._cs, HIGH);
  digitalWrite(fram._cs, HIGH);
  spi_end();
}

I think it’s a nice hack, and if you rewrite the loop as an ISR it could definitely free up CPU cycles. But the actual updating of the screen is still too slow for any sort of annimations.

Pepijn de Vos