Gameboy Emulator
tj963
Posts: 3
Hi all,
I'd just like to show off my most recent project and figure it may be interesting to some of you. I have built a working Gameboy emulator that runs actual cartridges. It started out as a discussion with some coworkers about what sorts of projects a Propeller was good for and somebody said, "No, you couldn't make a Gameboy emulator." And I thought, "Hmm, challenge accepted." After skimming through some docs and running through a few scenarios, it seemed plausible so off I went. It's taken almost a year to get here, but I have successfully played Tetris on it. Unfortunately none of my other test games work, but I've gotten far enough that I'm declaring victory .
YouTube video:
Images of the hardware:
https://drive.google.com/file/d/0B7qfDPDO_t9SRVBzSXRyNGV6QTg/view?usp=sharing
https://drive.google.com/file/d/0B7qfDPDO_t9SbnBpb01YazZQRHM/view?usp=sharing
https://drive.google.com/open?id=0B7qfDPDO_t9SaXRXQW55OFUtZ1U
The code is entirely PASM and is pretty complicated, particularly the cpu. It runs at a constant 24 Propeller instructions per Gameboy instruction (96MHz), and in order to maintain the timing and ensure hub accesses are always predictable there are NOPs throughout. It's also just two instructions short of the limit and I've already taken a lot of steps to compress it by reusing addresses, coverting two NOPs to READBYTEs, etc. Each Gameboy instruction has up to 8 Propeller hub instructions to execute it that are loaded from the hub, however normal instructions only have time to load three from the hub. Longer instructions will execute a JMP from the hub that puts them in a longer pipeline and some instructions or parts of instructions are implemented directly for performance. 2 bit TV output is the perfect number of colors for a Gameboy screen and sound is generated using a counter. I used a Wii Classic Controller Pro for input. They're surprisingly easy to interface with using I2C, though I had to split the I2C code up between video output lines because I ran out of cores.
The hardware is pretty straightforward. To get enough pins I had to add a switch for programming. The cartridges run at 5V so I've got two supplies and resistors on the data lines. The cartridge slot is a replacement for the GBA slot on a Gameboy DS. The controller connector is just some pads on the board.
The implementation is pretty complete. What's not implemented:
1. Link cable and stereo sound - Just not enough pins.
2. Wave sound channel - Tetris doesn't use it so I have to way to test it but there's no reason it couldn't be implemented.
3. The DAA instructions - More correctly the half-carry and subtract flags it requires. Not nearly enough cycles. You can see the that the score counts in hex.
4. There are some display and input bugs I haven't tracked down.
As to why the other games don't work, I have a few theories.
1. Write voltage. I'm writing though a 3.3K resistor to protect the prop on reads. I read this would for for the 5V TTL cartridges but never actually confirmed it.
2. Write timing is compatible with the cartridges. Tetris is ROM only, no memory bank switching so this is certainly a possibility.
3. A buggy instruction. I haven't tested them exhaustively, only what Tetris uses.
4. Some other emulation issue. A lot of the timing is pretty loose to work across multiple cores so this wouldn't be too surprising.
Overall, it's been a fun project. Programming for the propeller is quite enjoyable, predictable timing and lots of opportunities for tricks and optimizations. The debugging environment not so much. The GEAR emulator (with a few additions) was indispensable and I had Tetris running in it first, albeit glacially slow. Lack of a decent way to debug the actual hardware is one of the biggest hurdles in actually getting more games working. Porting to the actual hardware was mostly a formality since I had a test setup on a breadboard as well using an STM32F4 to emulate the cartridges since I had no practical way to connect them before the actual hardware was ready.
Finally, a big thank you to everyone who has taken the time to post on here. I've learned a lot from many of you from reading past discussions.
Source
DipTrace Schematic and Layout
Tim
I'd just like to show off my most recent project and figure it may be interesting to some of you. I have built a working Gameboy emulator that runs actual cartridges. It started out as a discussion with some coworkers about what sorts of projects a Propeller was good for and somebody said, "No, you couldn't make a Gameboy emulator." And I thought, "Hmm, challenge accepted." After skimming through some docs and running through a few scenarios, it seemed plausible so off I went. It's taken almost a year to get here, but I have successfully played Tetris on it. Unfortunately none of my other test games work, but I've gotten far enough that I'm declaring victory .
YouTube video:
Images of the hardware:
https://drive.google.com/file/d/0B7qfDPDO_t9SRVBzSXRyNGV6QTg/view?usp=sharing
https://drive.google.com/file/d/0B7qfDPDO_t9SbnBpb01YazZQRHM/view?usp=sharing
https://drive.google.com/open?id=0B7qfDPDO_t9SaXRXQW55OFUtZ1U
The code is entirely PASM and is pretty complicated, particularly the cpu. It runs at a constant 24 Propeller instructions per Gameboy instruction (96MHz), and in order to maintain the timing and ensure hub accesses are always predictable there are NOPs throughout. It's also just two instructions short of the limit and I've already taken a lot of steps to compress it by reusing addresses, coverting two NOPs to READBYTEs, etc. Each Gameboy instruction has up to 8 Propeller hub instructions to execute it that are loaded from the hub, however normal instructions only have time to load three from the hub. Longer instructions will execute a JMP from the hub that puts them in a longer pipeline and some instructions or parts of instructions are implemented directly for performance. 2 bit TV output is the perfect number of colors for a Gameboy screen and sound is generated using a counter. I used a Wii Classic Controller Pro for input. They're surprisingly easy to interface with using I2C, though I had to split the I2C code up between video output lines because I ran out of cores.
The hardware is pretty straightforward. To get enough pins I had to add a switch for programming. The cartridges run at 5V so I've got two supplies and resistors on the data lines. The cartridge slot is a replacement for the GBA slot on a Gameboy DS. The controller connector is just some pads on the board.
The implementation is pretty complete. What's not implemented:
1. Link cable and stereo sound - Just not enough pins.
2. Wave sound channel - Tetris doesn't use it so I have to way to test it but there's no reason it couldn't be implemented.
3. The DAA instructions - More correctly the half-carry and subtract flags it requires. Not nearly enough cycles. You can see the that the score counts in hex.
4. There are some display and input bugs I haven't tracked down.
As to why the other games don't work, I have a few theories.
1. Write voltage. I'm writing though a 3.3K resistor to protect the prop on reads. I read this would for for the 5V TTL cartridges but never actually confirmed it.
2. Write timing is compatible with the cartridges. Tetris is ROM only, no memory bank switching so this is certainly a possibility.
3. A buggy instruction. I haven't tested them exhaustively, only what Tetris uses.
4. Some other emulation issue. A lot of the timing is pretty loose to work across multiple cores so this wouldn't be too surprising.
Overall, it's been a fun project. Programming for the propeller is quite enjoyable, predictable timing and lots of opportunities for tricks and optimizations. The debugging environment not so much. The GEAR emulator (with a few additions) was indispensable and I had Tetris running in it first, albeit glacially slow. Lack of a decent way to debug the actual hardware is one of the biggest hurdles in actually getting more games working. Porting to the actual hardware was mostly a formality since I had a test setup on a breadboard as well using an STM32F4 to emulate the cartridges since I had no practical way to connect them before the actual hardware was ready.
Finally, a big thank you to everyone who has taken the time to post on here. I've learned a lot from many of you from reading past discussions.
Source
DipTrace Schematic and Layout
Tim
Comments
Totally awesome.
We must have three emulators for the 8080 like processors on the Prop now. My ZiCog Z80 emulator is a couple of Z80 instructions short but enough to run CP/M. Pullmoll's qz80 is complete I believe.
That DAA instruction is a pig to get right. If I remember correctly the 8080 and Z80 don't behave the same way for DAA.
The guys wanting a 6502 emulator on the Prop are lagging behind
Are you going to put the code up somewhere we can access it from? Github or Bitbucket say.
Yeah, they seem to be pretty popular. The Gameboy processor is a weird combination of the 8080 and the Z80 so we've got a few different variants.
There's a Drive link in the initial post or I've also uploaded it here: https://github.com/tj963/PropellerGameboy
It's probably not easy to read, but I can try to answer any questions about it.
Can't get into Google Drive without registering. Github is much better.
It's been such a while since I did any serious Prop PASM or Z80 hacking it might take some time to get up to speed. Staring out it now...
Very cool project...awesome job
Did you have any problems with the stm32f4 and the propeller interfacing...the reason I ask...the stm32f4 runs at 3.0v but the propeller is 3.3v. The stm32f4 has an +-.3v but the seems very close to the max voltage
No, I didn't even know that there was a difference. I based it off off the implementation here: https://dhole.github.io/post/gameboy_cartridge_emu_1/