How To Make Dmg Gameboy Worthwhile

  




If your cartridge has Nintendo Game Boy™ written on the front, it's most likely real, however in some cases reproductions may look a lot like a real cartridge, it is suggested to open it to make sure. Return to main page. Jul 17, 2008 Doubt it:P. The GB's been released and cloned a dozen times over. The resale market is filled with them. A Game Boy Classic Edition contributes nothing in terms of function, where the NES and SNES equivalents brought very significant product offerings (cheap, well-handled digital output, and in the SNES case, a highly touted unreleased game) to the table. PiBoy DMG is a complete hand held gaming system powered by a Raspberry Pi. PiBoy is compatible with the Pi 4B, Pi 3B or Pi Zero. With the Raspberry Pi 4 take emulation to the next level. Play N64, PSP, Dreamcast and more games like never before. Make sure all required tools and libraries are in%PATH% and%lib%, respectively. (see Build FAQ for more details on Windows compilation) To compile, simply run make. The targets are cocoa (Default for macOS), sdl (Default for everything else), libretro, bootroms and tester.



ASMSchool - Lesson 1

Welcome to ASMSchool, my own little attempt at helping people to learn how to code in assembly language on the GameBoy using RGBDS. These tutorials will hopefully be of use to quite a few people, both total newbies and more experienced coders. I am NOT going to just post some source code, give comments and have you cutting and pasting, that won't teach you very much of anything. Instead, I will be going to the lowest levels and explain everything in as much detail as I can so that you can understand 'why does this do this' or 'why can't I do that?'. You will learn how the processor works and how to control it before I ever start writing lessons on how to display graphics or how to make sound. Lesson 1 will teach the student about the layout, structure, and general philosophy behind the GameBoy CPU, as well as basic data manipulation. This CPU is a derivative of the very popular 8-bit Zilog Z-80 CPU, and has many identical features, although the GameBoy's CPU includes memory handlers, I/O control, and other things not found in the Z80 on-chip. There are also a few things that the Z80 has that were taken out of the GameBoy, as they were deemed by Nintendo R&D as unnesecary. (either that or SHARP's custom chip didn't have those options available. who knows.)

Lesson 1: Description and Processor Theory

Ok, so you're probably thinking, 'where do I start?' or 'how do I make a game?'. Well, we are a LONG way from making a game. You have to learn the hardware and how to manipulate it way before you can even make anything worthwhile. I'm going to start here with the basic structure of the GameBoy's CPU, and then explain how you can make it do your evil bidding! MWA HA HA HA HA HA HA!!!.... uh hrm.. oh sorry. ;-) Well to do ANYTHING with a CPU, you have to MOVE and OPERATE on DATA! And how on earth are we going to do that? Well, with registers that's how. Registers in the CPU are where all data is handled and processed.

Registers

Working with and manipulating data with this processor is accomplished through the use of 8 registers inside the CPU. Each of these registers can hold 8-bits or 1 byte of data. The registers can also be paired up to form 16-bit registers for tasks such as addressing data. The names of these registers are A, F, B, C, D, E, H, and L. They can be grouped to form the 16-bit registers AF, BC, DE, and HL. There are also the 16-bit registers SP and PC. Each of these registers has it's own little part to play inside the CPU.
The A register is where almost all data being processed passes through. It is also known as the Accumulator (No, not because it's accumulating dust either!). This register, as well as B, C, D, E, H, L can have data loaded into it directly.(I purposely left out register F) By this I mean you can just say 'I want the A register to contain 25!'. You don't specifically have to load a value from memory somewhere. It is the only 8-bit register that can be shifted with a one-byte instruction (you'll find out about SHIFT instructions later). It is the only register that can be complemented, decimal adjusted, or negated with a single byte instruction. It is the source AND destination for all 8-bit arithmetic and logical instructions except for INC and DEC, which increment or decrement a register by 1. This means that when you want to perform a certian operation like ADDing two 8-bit registers together, the two numbers you'd want to add would be in A and some other 8-bit register, then the answer would be left in A after the operation was completed. Simple eh?
The F register (F for Flags) is a processor status register that can only be read from and not written to, with one exception. Four of the bits in this register indicate the outcome of generally the last operation performed. One bit indicates whether the last operation produced a zero or not, another bit indicates whether or not the last instruction generated a carry, yet another indicates whether or not the last instruction performed a subtract, and a half-carry flag in case a carry is generated between nybbles in a byte.
The B and C registers are generally used as counters during repetitive blocks of code such as moving data from one location to another.
Registers D and E are generally used together as a 16-bit register for holding a destination address in moving data from one address to another. They can be used for other operations though, as much as the instructions will permit.
The H and L registers are special due to the fact that they are extensively used for indirect addressing as register pair HL. Indirect Addressing is when instead of specifying an specific address for an operation, you could just use the 16-bit value in HL as an address. It's pretty handy for things like address calculations when you need to access an array of value for example. This is the ONLY register pair that can be used indirectly in the instructions ADC, ADD, AND, CP, DEC, INC, OR, SUB, and XOR.
The SP register is the Stack Pointer, where values from PUSH, POP, CALL, and RET instructions are placed or taken. These values are return addresses for subroutines and such. When the GameBoy is initlaized, this register contains the value $FFFE. On the GameBoy CPU, the Stack grows from TOP DOWN. The means that when you PUSH a 16-bit value to the stack, it hangs down the address space from the top like a stalactite (or is it stalagmite? I can never remember).
The PC is the Program Counter. This register tells the CPU the address that the next instruction is to be fetched from in memory. When the GameBoy starts up, this register contains the value $0100.
Well, those are the GameBoy's CPU registers. So now that you think you know those, we'll jump right on into the instructiuons that get to play with those registers. Can you hear it? Can you? Can you? I hear the sound of data screaming! We're coming to get you data! Cower in fear little data for a new ASM coder is born!!! MWA HA HA!!!

Instruction Set

The instructions in the instruction set for the GameBoy CPU are also known as opcodes. These opcodes are grouped into 8 general categories.
  • 8 and 16-bit Loads
  • 8-bit Arithmetic and Logical Instructions
  • 16-bit Arithmetic Instructions
  • General Purpose Arithmetic and CPU Control Instructions
  • Rotate and Shift Instructions
  • Bit Manipulation Instructions
  • Jump Instructions
  • Call and Return Instructions

Lesson 1 will cover the 8 and 16-bit load instructions and some general ideas. Lesson 2 will consist of 8 and 16-bit Arithmetic instructions and Logical instructions. Lesson 3 will cover General Purpose arithmetic and CPU control instructions as well as rotates, shifts, and bit manipulation. Lesson 4 will be Jump Instructions and Calls and Returns for program flow control, including all the CONDITIONAL Jumps and Calls.

8 and 16-bit Loads

Well, when programming, your ultimate goal is to manipluate data, as simple as that might sound. Simple yes. Easy, not nessecarily. These instructions are what move data to and from registers, memory, and oblivion (in the case of directly loading a fixed value into a register).

Register to Register Transfers

The LD (load) instruction can transfer any 8-bit general-purpose register (A, B, C, D, E, H, or L) to any other 8-bit general purpose register. The F register can only be transferred to or from the stack, along with the accumulator as register pair AF (PUSH AF and POP AF).
The common transfer instructions are:
  • LD A, reg - Transfers the contents of reg into the accumulator
  • LD reg, A - Transfers the contents of the accumulator into reg
  • LD reg, (HL) - Load reg with the value at the address in HL
  • LD (HL), reg - stores reg at the address in HL

Note the the destination of the data comes first in the operand field of the LD instruction. The LD instruction changes ONLY the destination, the source stays intact. Rather than being a MOVE style of instruction, it is rather a COPY of the source contents to the destination contents.
Now you try...
  • LD A, B
  • LD C, A
  • LD A, (HL)
  • LD (HL), A

See? Was that really difficult? The first instruction loaded the contents of register B into register A. The next instruction loaded the contents of register A into register C. The third instruction load the memory contents located at the address contained in HL into register A. That might seem a bit wordy, but its just a way to use HL as an address place holder. The last instruction does just the opposite.

Direct Loading of Registers

The accumulator, register pairs BC, DE, or HL, and the Stack Pointer can be loaded from memory using Direct Addressing. Some examples of this are:
1. LD A, ($3FFF)
This instruction loads the accumulator (register A) from memory location $3FFF.
2. LD HL, ($A000)
This instruction loads register L from memory location $A000, and register H from memory location $A001. Note the practice of storing the Least Significant byte at the lower address. Oops! No wait! This instruction isn't viable on the GameBoy CPU! (just checking the experienced coders) You can't just load H and L from two memory locations with one instruction, you must load each one independently when load from memory. When loading a direct data value you CAN do that though.
3. LD SP, ($4050)
This instruction loads the Stack Pointer from memory locations $4050 (least significant byte) and $4051 (most significant byte). All subsequent stack operations such as PUSH or POP will be located at that new address loaded from that loacation, EG.. if at $4050 the data was $00 and at $4051 was $C4, then the Stack Pointer will contain $C400 and all stack operations will happen there. Notice how the less significant byte of a 16-bit address is stored at the LOWER address.

Immediate Loading of Registers

Immediate addressing can be used to load any specific register or register pair with a specific fixed value. This also includes the Stack Pointer and the Program Counter, though you shouldn't directly load the Program Counter unless you really know what you're doing, since that is where the CPU get the address for the next instruction to execute. Some more examples follow.
1. LD C, 3
This instruction loads register C with the value 3. The 3 is an 8-bit data item, NOT a 16-bit address. Also, do not confuse the plain decimal 3 with $0003, even though they are relatively equal.
2. LD DE, $FF80
This instruction loads register pair DE with the value $FF80. This would be the same as loading register D with $FF and loading register E with $80.

Indirect Loading of Registers

The instruction LD reg, (HL) can load any 8-bit register from the address in register pair HL. The instruction LD A, (rp) can load the accumulator from the address in register pairs BC, DE, or HL. A is the only register that can use BC and DE with indirect addressing. Note that there is no instruction to load a register pair indirectly, so you CANNOT say something like LD DE,(HL) or LD HL,(A000h). Examples:
1. LD D, (HL)
This instruction loads D with the byte located at the address in register pair HL.
2. LD A, (BC)This instruction loads the accumulator from the memory address in register pair BC. Note that you cannot load any register besides A using BC or DE indirectly.

Stack Loading of Registers

The instruction POP rp (rp is a register pair) loads a register pair from the top of the stack. Remember, that the stack in the GameBoy grows from top-down, so the top of the stack is the lowest address occupied by the stack, which is indexed by the Stack Pointer. Of course, POPping from the stack INCREMENTS the stack pointer by 2, to point to the new top-of-stack address. PUSH is how you store a register pair to the stack. These two instructions are great for temporarily saving registers if you need to use them for something else (since there's only a few registers).

Storing Registers in Memory

Well, we talked about loading registers from memory, I guess we should now talk about storing them TO memory. The concept is really easy now that you know how to LD a register. To store registers, you just turn the operands around in the previous examples I gave you. Remember in Z80 and GameBoy assembly code, the structure of an instruction is the OPERATION first, then the DESTINATION, then the SOURCE. Like this:
LD dest, source
All you gotta do to store a register is change the destination to a memory location instead of a register and make the source a register. Here's an example:
LD ($C000),A
This just loads the contents of A into the memory location $C000. Note that there are brackets around the memory destination. This is to distinguish the address $C000 from the actual plain 16-bit data value of $C000. You can also do things like:
LD (HL),C
This just moves the contents of C to the address contained in HL. Is that pretty simple or what? =)
Ok, well say you want to store a specific value in memory, like maybe.... $6F. Well how would we do that? You could do it a few ways. Let's start out by loading HL with the destination memory address. Then we have to use that address in HL as a destination in memory to load a register to:LD HL, address (eg: $8000)
LD (HL), A <-loads contents of register A into memory location at HLorLD HL, address
LD (HL), $6F <-loads value $6F into memory location at HL
Now those weren't too hard right?
For all the specific limitations and abilities when using the LD opcode, see the instruction set reference guide also on my webpage.




Getting Started!

I had recently bought an original Gameboy DMG from Good Will for a whopping $5.00, condition unknown. Taking a gamble, I purchased it and took it home to find that it had severe damage caused by a battery that exploded and leaked all over the mainboard.

I had also recently started looking on eBay for the elusive Gameboy Light. It’s a system I have always wanted but could never allow myself to buy since they are pretty expensive on eBay. The Gameboy Light is the Gameboy Pocket with an Indiglo light and was only released overseas in Japan.

I had bought a Raspberry Pi a while back and really didn’t know what I wanted to do with it. At that moment, like a Reese’s Peanut Butter cup, it dawned on me – could the Raspberry Pi be used with a Gameboy?

The Raspberry Pi is a small ARM based computer that fits in the palm of a normal adult hand. The great thing about the Pi is that it has several ways to connect I/O for video, audio, network, USB as well as a direct I/O set of pins called the GPIO pins.

After doing some research, I came to the conclusion that this project might actually be conceivable. Everything I needed was there, it was a matter of getting things together and working out the hardware as well as software side of things. That’s where this guide comes in. It’s my attempt to pass on what I’ve learned as well as taking you through the various steps I took to make it a reality. First off, the parts…

The Parts List

Hardware

  • Broken Gameboy DMG (please don’t sacrifice a perfectly good working one)

Software

Tools

  • Dremel
  • Soldering Iron
  • Solder
  • Wire Cutters
  • Electrical Tape
  • Hot Glue Gun
  • Electrical Wire
  • Exacto Knife
  • Patience…

The Case

The first thing that had to be done was to see if the Pi would even fit into the case. I found that the Pi sits almost perfectly on the back case of the Gameboy. The width of the Pi fits snug down the center of the case, but in order for it to fit, some modifications had to be done to the case itself.

Using a Dremel, I cut out a most of the battery compartment as well as some posts that on the case for the LCD that would no longer be needed. Doing so, the Pi sits flush with the back of the DMG case:

How To Make Dmg Gameboy Worthwhile

In the picture above, the battery compartment is on the left and the cartridge slot is on the right. I had to cut back the Cartridge slot as well in order to allow the GPIO pins to fit.

I had initially cut a slot on the left thinking I would add a wireless keyboard or network dongle which can still be added. This would use additional power which means more drain on the battery so those were left out.

LESSON LEARNED – given that, I probably should have de-soldered the Network and USB ports to slim up the Pi which would have allowed for more room to work with.

The Screen

The screen was the first challenge. The screen runs off 12V out of the box which wouldn’t work with the USB battery pack. The USB battery pack is rated at 5V, 1000mAH so the goal was go modify the screen to allow it to run at 5V.

Luckily, there is a great thread here: http://www.raspberrypi.org/forums/viewtopic.php?f=41&t=17651 which details how to modify the PCB for the screen to run at 5V instead of 12. The problem with these screens is that there seem to be several versions of the PCB controller boards which require different approaches.

For my particular setup, the board came with the 4 wires (yellow, white, black and red) all soldered onto the PCB. I found a board in the thread above that matched my board, but I still had some difficulties getting the board to run off of 5 volts.

I finally got it to work by removing the power converter chip as well as soldering a jumper between the + power in and the capacitor on the top right as seen below:

The next step was to hook a composite input to the screen PCB board. For this, I took a composite wire I had and stripped off the connector to create a smaller connector that would fit into the Pi’s female composite port. The Pi composite input could have been de-soldered, but I chose this approach to allow it to be unplugged from the Pi if needed.

The Yellow wire from the LCD Controller is soldered into the Composite input. The Black wire (ground) is soldered from the LCD Controller board as well and then wired to the male composite connector. You can see the connector on the left side of the image below
After this was completed, the screen and Pi were plugged into a 5V USB input and tested.

Success!

The next challenge was fitting the LCD and controller board to fin in the case. I initially wanted to keep the size of the original Gameboy window and add on a new screen protector. I tried orienting the screen in a portrait layout, but this proved problematic with Retropie.

Editing the root “config.txt”, you have the ability to rotate the screen as well as adjusting the overscan of the screen. The config.txt file can be edited directly from your SD card with any PC. Here is a handy guide to the various settings that can be tweaked and adjusted in the config.txt: http://elinux.org/RPiconfig

None of the adjustments made yielded a layout that would fit correctly within the Gameboy’s window. I made the decision to go ahead and cut out the window to allow the screen to be displayed.

This also meant that I would have to layout the screen in a landscape orientation. This would not work without some trimming of the LCD Controller board since it’s wider than the width of the Gameboy. The parts outlined in red below are what needed to be cut to get the board to fit.

After multiple cuts and trims, I found that I was able to BARELY fit the Controller Board into the case. It only fits because part of the controller board sits in the position where the original Gameboy Contrast knob used to sit. However, it does fit!

For the LCD, I used black electrical tape to cover up the silver border of the screen. Once this is done, I used some double sided stick padded tape and trimmed it to form a border around the LCD and then mounted it to the case.

The Controls

After getting the screen to work, the next step was to get the controls to work. I decided that I would try to use the Pi’s GPIO inputs instead of getting something like a Teensy board. Adding another board would mean that I would have to find room in the cramped DMG case and the GPIO pins are already there, waiting to be used!

I stumbled on a company that creates Controller boards for DMG Gameboy’s that works perfectly with this setup. Instead of having to take the original Gameboy PCB, cutting it and having to solder in wires, the Kitsch Bent PCB allowed me to solder directly to inputs built right into the PCB.

Below is the Controller PCB. The PCB screws into the existing Gameboy mounting posts so the original buttons and rubber fit right in like the stock board would fit. The arrow points to the solder points with each point clearly marked off with it’s respective control function. This makes it easy to associate a control to a solder point which was tied to a specific GPIO pin.

The other advantage of this was that the Kitsch Bent version uses a common ground. This meant that I only need one ground wire for all of the buttons.

Initially I had bought some wires with female to female connectors that I thought I could just plug into the GPIO pins with. This proved to be a failure since the wires sat too high and could not be bent. I decided to strip the wires and solder them directly to the GPIO pins. This proved to be a mistake that caused me unneeded work and issues when trying to assemble everything together.

LESSON LEARNED – I should have bought a GPIO ribbon cable similar to this: http://www.adafruit.com/products/1337. This would have been a simple plug and go solution instead of the pain of soldering the wires to the pins and having them pull off as I tried to work around things.

Once the pins were all soldered to each of the wires, it was time to setup the Retrogame program that would handle each of the input controls.

I followed this guide https://learn.adafruit.com/retro-gaming-with-raspberry-pi/buttons which details the steps needed to map a GPIO input to a corresponding keyboard key. I mapped out the keys based on the following which worked out great for all of the inputs I needed:

Once the program was updated, I compiled the updated version of the code and added the entry to autostart as the Pi booted. I had to make a couple of adjustments for the ESC key in Retropie and had to double map the A button to on the Gameboy to be an S on the keyboard as well since the PC Engine emulator seemed to want to use the keyboard S key as one of it’s buttons.

I also decided that I needed some extra controls since I intendedto run the Gameboy Advance emulator as well which would need shoulder buttons. I decided to mount to buttons I found at Radio Shack that would work.

The position of the buttons seems to work better than putting them on the side. My middle fingers fall onto these buttons with the natural grip of the DMG case which works great. These buttons also map to the Page Up/Page Down keyboard keys which I use for paging back and forward through the ROM lists.

For these buttons, these each needed their own ground so I used some of the free GPIO ground pins for each. You can see these in the GPIO mapping diagram above.

Audio

The first thing I had to do was figure out a way to connect to the Pi’s audio out port. I considered de-soldering, but utltimately found that I could just take an old pair of earphones and cut the Input Jack’s rubber shielding to expose a pin with 2 solder points that I could wire to. This allowed me to use an Earphone Jack to essentially plug into the Pi’s audio out jack without desoldering anything. Doing this, I wired directly to the speakers at first only to find that the sound was… lacking!

I ended up ordering an Audio Amplifier board from eBay (above) and connected it to the Pi’s Audio out. The Audio Amplifier requires 5 Volts of power to run, so I soldered wires from the LCD Controller Board’s Positve solder point to the +5V/Ground of the Audio Amplifier.

I wired in the wires from the Pi’s Audio out to the RIN/GND (bottom left of the Audio Amplifier board) and then wired the speaker to the R+/R- (top left of Audio Amplifer board). This drastically improves the loudness of the speakers.

Worthwhile

How To Make Dmg Gameboy Worthwhile Games

I had originally wanted to use the Gameboy’s Sound Control potentiometer, but it was impossible to find a way to mount and I ended up just scrapping that idea.

Retropie includes a Volume adjustment bar in it’s menu so that’s how volume is controlled.

The Emulators

This was somewhat simple and can be summed up with one word – Retropie. You can download bootable image which can be written to an SD card which will provide you with the Raspian operating system as well as it auto booting to Retropie. Check out the Retropie forums for more details on installing, configuring and troubleshooting Retropie.

Wiring the Beast Together

Here is the wiring schematic for how everything was tied together:

The battery is connected to a Female Micro USB port that I hot glued into place. I modified the port where the Headphone jack was located widening it so that the Female Micro USB adapter would fit.

(1) The Female Micro USB Positive (RED) wired is then fed to the On/Off Switch. From the switch, the Positive (RED) wire is soldered to the positive solder point on the LCD Controller Board.

The Ground (BLACK) from he Micro USB port is wired directly to the negative solder point on the LCD Controller board.

(2) The Positive (RED) and Negative (BLACK) wires are then wired from the Positve/Negative points on the LCD Controller board and then wired to the Micro USB Male pin that is plugged into the PI.

The Audio Amplifier is also wired to the Positive/Negative points on the LCD Controller Board. The Positive (RED) wire is connected to the +5V solder point on the Audio Amplifier and the ground (BLACK) is wired to the GND right above the +5V solder point on the Audtio Amplifier. Since the LCD is power in runs through the switch, anytime the switch is flipped, the LCD, PI and Audio Amplifier are all turned on or off at the same time.

How To Make Dmg Gameboy Worthwhile Pc

(3) For video, the positive Composite wire (YELLOW) is wired to the positive solder point on the Composite connection plug. A Negative (BLACK) wire is also soldered between the LCD Controller board and the solder point on the Composite connection plug.

(4) The audio Amplifier is connected to an Audio input jack by connecting the Positive (LIGHT BLUE) and Negative (BLACK) to the GND and RIN solder points on the Audio Amplifier.

How To Make Dmg Gameboy Worthwhile Computer

(5) the R+ is wired (ORANGE) to one solder point on the speaker and the R- (GREEN) is wired to the other solder point on the speaker.

Overview Videos

Part 1:

Part2:

Make

Final Thoughts…

I love my “Super Mega Ultra Pi Boy 64 Thingy”! It was a lot of fun to build and was well worth it. I recommend just taking your time and doing some research before just jumping in. I’ve tried to layout as much as I could above, but if you have any questions, please leave them in the comments below!

Also, if you build your own version of this project, I would love to see it as well!

Thanks for reading…

How To Make Dmg Gameboy Worthwhile

Helpful Links

How To Make Dmg Gameboy Worthwhile Without

  • Raspberry Pi Gameboy Pocket Documentation – AMAZING Pi Gameboy Pocket mod with some excellent build details