Close
0%
0%

WIFI Game Boy Cartridge

ESP32 emulating to be a cartridge

Similar projects worth following
Using the Game Boy as a remote control is a childhood dream of mine. Having it connected to the web was later on on the top of the list of things I wanted to have for this sweet machine. So that's what I'am aiming at: control stuff over the web with a Game Boy.

Or may be war driving with a Game Boy, controlling MQTT stuff and browsing http://retro.hackaday.com/ - depending how far I get.

The ESP32 parts in Arduino are licensed under http://www.apache.org/licenses/LICENSE-2.0, my work will be published under the MIT License (it's in the file section).


The goal

My plan is to achieve a working environment for the ESP32, to handle the requests of the game boy and work with wifi in parallel, so that you can actually use the Game Boy to surf or interact live with the web/wifi. There are many possibilities to take something useful out of it.


Choice of Hardware

Right now I only want to concentrate on one chip and focus on replicating results that are equal to the achievements of dhole [emulating with STM32] or Alex of insidegadgets.com [emulating on Arduino], where dhole managed to emulate not only ROM but also RAM and MBC (memory bank controller) on one chip. I was about to start with an additional Flash or EEPROM and an ATSAMD21 as an MBC, but that would mean programming two firmwares for two chips that I haven't worked with before - plus programming the actual code for the Game Boy side. The first idea was to use an ESP12 module as an MBC, but with only one core to handle WiFi and inputs at that level of speed would have been impossible (IMHO).


Cartridge vs. Link Port

I do like the approach of using the linkport to talk to an ESP12 and think it is feasible to go that route [like flying a drone]. But it would also require two components: an EEPROM cartridge AND an ESP dongle on a port that no one builds plugs for anymore. From a hardware aspect it is much easier to do an egde connector on a pcb and wire up the ESP, so that's another reason to go with a cartridge. You would also need to build and program your own cartridge, like I did on my other project: #Game Boy Cartridge plus Programmer - instead of using an USB ready ESP board in a cartridge form factor.


Choice of IDE

I'm currently using Arduino IDE, I've done a lot with it so far and am a creature of comfort. There are ways to implement features and functions to bypass "crappy" Arduino code. But it's written better then everything I could have come up with and I've heard of good changes that were made to the Arduino code recently. I hate the crappy editor, love sublime. Integration of Arduino into Sublime was always buggy for me. I love just pushing a button to upload code.


Speed of pin toggle

The current way that I use to toggle the pins and also read them is way too slow. As stated [here], the max speed with direct pin toggling through registers is about 4MHz, far from the cpu speed of 240MHz. In comparison the plain olde Arduino with 16MHz CPU has a toggle speed of round about 2.66MHz, when changed through port registers. You can find the ESP32 pin toggle function [here].


Using I2S as parallel input and output bus

Now I'm really leaving the sector of stuff that I'm used to do or comfortable with (I'm a PHP/JS guy in real life). I don't often surf around the latest CPP code written by CNLohr and SpriteTM, but when I do.. well I don't. But I want to work on that cartridge as long as I see there is an option to go on. In comes the code of CNLohr [github link] - and the previously unknown to me parallel I2S bus.

Adobe Portable Document Format - 35.26 kB - 12/14/2019 at 01:28

Preview
Download

plain - 1.03 kB - 04/26/2017 at 18:25

Download

  • 1 × ESP32 module
  • 3 × 74LVC8T245 Logic ICs / Receivers, Transceivers

  • Infomercial: someone succeeded in creating a WiFi cartridge

    davedarko12/16/2021 at 14:27 0 comments

    I've been recently contacted by Sebastian, asking me things about this project because he made a WiFi cartridge. We talked a bit about the hurdles I faced and now there's a video of his project out and here's a link to his blog post as well.

    http://there.oughta.be/a/wifi-game-boy-cartridge

  • Soldered a prototype, found a bug

    davedarko12/14/2019 at 13:58 0 comments

    Finally decided on soldering a PCB and when I programmed it, it wouldn't start the program afterwards. So I was calling for help on twitter and got some well meant advices about pulling certain pins that no ESP32 dev board pulled up. It took me a while to notice that I was missing the capacitor in my reset circuit. I didn't check what C6 actually does while debugging, so I thought being so close to the ESP reset pin and resistor, that it was part of it. With a bodged on capacitor it now resets to run the program!

    So far it's only a cartridge shaped ESP dev board that can talk to 5V devices, but it's good to know this is programmable!

  • exiting views

    davedarko03/06/2019 at 21:11 0 comments

    Some nice beautiful purple boards arrived at home today, but I'm trapped with three dudes in a trailer house in Luxembourg for the next 12 days :D

  • Let's do some test boards

    davedarko02/08/2019 at 09:12 0 comments

    I'm scared of that rats nest of wires on a breadboard that is hidden in a box. Thanks to some experience I gained with using IO0 and IO2 as a regular pin, I know that it's okay to use them as the missing two address line pins. I might steal one of them back to be able to reset the game boy, as I don't think using one of the serial pins is a good idea, especially if you want to have a serial debug terminal ;) 

    With less address pins the programs written / compiled for should adjust memory bank switching for smaller banks. I think that's doable. 

    Not sure if I said this here, but I was able to run the I2S parallel code on the ESP32 and that gave me hope. After a lot of unexpected twitter feedback about groundplanes and copper tunges, I made some changes and this is what I came up with. Cleanly routed, doesn't fit any reproduction cartridges, but form follows function, right? There's even a 1M ohm connecting the usb connector shield to Ground (not even sure if this is 100% necessary, but better safe then sorry, right? 

    Power consumption of the ESP vs. 4 AA batteries inside a DMG or even worse - 2 AAA batteries inside a GB Pocket is still an issue with this board. The plan is to have one AAA LiPo added to a later revision of the board. To get an idea how this could look like, check out the Pokemon Pinball cartridge, or any Game Boy rumble cartridge for that matter. This design is supposed to be powered over USB, since it's a dev / debug board.

  • from the hackchat

    davedarko03/09/2018 at 16:24 2 comments

    Me: I have this project idea: #WIFI Game Boy Cartridge - I was a bit naive when I started this, tried to toggle pin for pin but it was way too slow. Would/could this work with the I2S parallel interface? I wasn't able to find much on the I2S interface when I started this and what I found was above my skill set, but I still like the idea of having a cartridge that has wifi.

    Sprite_tm says:4:31 PM
    Ah, I saw that. Did something like that on a Vectrex with a CortexM4.

    Sprite_tm says:4:32 PM
    Wrt the WiFi GB cartridge: Long story short, I don't thing I2S is the right way to go there.

    Me: okay, any right ways?

    Sprite_tm says:4:33 PM
    The issue mostly is that you need to see that a CS line goes low, then immediately read the address lines, look up whatever you want to send back and send it.

    Sprite_tm says:4:34 PM
    I think that I2S would be too slow for that; you'd have to set up a transaction and everything. I think you could get it to work if you wrote a high-prio interrupt for the CS pin, then in the interrupt handler, in assembly, read the address GPIOs as fast as you can, grab a response from internal memory (which luckily you have more than enough of) and send that to the data pins.

    Sprite_tm says:4:35 PM
    If you need help with that, poke me; by now I have some experience with high-level interrupts and I'm actually curious if the ESP32 can do it, but don't really have any interesting consoles here.

    Me: I thought "as fast as I can" would be I2S, since there's no way of getting pins parallel

    Sprite_tm says:4:37 PM
    You might get it to work... but there's a fair amount of setup using the I2S peripheral. It may still be quicker than doing it manually, I agree.

    Sprite_tm says:4:39 PM
    @davedarko Maybe a good idea to move on to other qs... if there is still time at the end, I'd love to come back to it. For now, feel free to poke me at [mail] for this.


    http://esp-idf.readthedocs.io/en/latest/api-guides/hlinterrupts.html

  • Starting with esp-idf-v2.0

    davedarko06/16/2017 at 20:23 0 comments

    http://esp-idf.readthedocs.io/

    Finally found the time and inspiration to work on this project again. To get the I2S demo of CNLohr working, I also needed to be able to compile with the esp-idf.

  • celebrations are in order

    davedarko05/14/2017 at 21:37 3 comments

    http://hackaday.com/2017/05/14/hackaday-prize-entry-wifi-game-boy-cartridge/


    I feel some questions are coming my way, so I've updated the detail section :)

  • precognition in a game boy?

    davedarko05/13/2017 at 12:24 3 comments

    So I thought to myself, if the ESP is too slow, but the query itself is taking microseconds instead of nanoseconds: why not trick the ESP and spit out the next in array? here's what I got, admittedly one of the better results, but you can finally read something! I can live with it, if I can get it to work reliably.

  • i2s for parallel IN / OUT?

    davedarko05/12/2017 at 23:14 1 comment

    https://www.esp32.com/viewtopic.php?f=19&t=1746&p=8153&hilit=parallel#p8153

    Seems like I'm 3us late with reading and preparing my response. The posted scan looks like it takes 175us from address change to address change. Putting it in relation, an EEPROM takes 150ns to respond, that's 1/20 of the time I have now. With 240MHz the ESP32 should have a clock cycle time of 4.16ns. Whaaaat? My math is broken. Seems like the maximum speed for gpios on the ESP is "quite" limited, max toggle freq is around 4MHz. https://www.esp32.com/viewtopic.php?f=2&t=1595&p=7482&hilit=parallel#p7482

    Seems like there is a multipin IS2 interface that was also used on https://github.com/igrr/esp32-cam-demo/blob/master/components/camera/camera.c#L314

    https://www.esp32.com/viewtopic.php?f=12&t=951&p=4113&hilit=parallel#p4113

  • moar research.

    davedarko05/12/2017 at 18:48 0 comments

    So from far away it looks alright! I checked every byte and the data is correct. But...

    Look a bit closer and you see this:

    It might make sense to give the ESP the control over the OE of the data pins, since it's not fast enough to react to every change on the fly, it might needs better timing.

View all 18 project logs

Enjoy this project?

Share

Discussions

Jakob Brömauer wrote 12/28/2021 at 18:07 point

Hey Dave, great Project. I know what you are going trough, I have also managed to build a Game Boy cartridge running on a STM32. You can check it out here: https://hackaday.io/project/179717-serial-boy/

Dont give up, all the best, Jakob

  Are you sure? yes | no

David Konsumer wrote 03/09/2020 at 17:41 point

I am making https://github.com/konsumer/dkart We definitely have some similar ideas.

I started on the GB side, and my original hardware design was a lot more complicated with a custom PCB, but for now, I am really into just trying to use a cheap ESP32 dev-board with a cart-adapter (just a simple PCB with a spot for SD & ESP32 dev-board pins.) My goal is a mostly software-designed setup on easy-to-assemble & cheap hardware.

You are welcome to use my GB-side menu program for yours. It works by reading page-by-page from SRAM (which the cart will emulate.) I'm still working on ideas, but it shows a splash screen, manages a menu, and makes sounds when you do stuff. Even if you don't use it as-is, it might give you some ideas.

Your cart should emulate these (GB SRAM addresses) if you want to use it as it is :

```

// the page var that GB writes to tell cart what page to serve up

unsigned int* PTR_CURRENT_PAGE = (int*) 0xA000;

// the current ROM to load, from current page

unsigned int* PTR_CURRENT_ROM = (int*) 0xA001;

// the total number of ROMs on SD
unsigned long* PTR_ROM_COUNT = (long*) 0xA002;

// the names (max 20 chars) of the ROMs on current page, in a size-15 array

char* PTR_ROMS = (char*) 0xA010;

```

At first I thought I might use a command-system (save particular data to RAM addresses to trigger things) but I realized that I will know the current ROM that is loaded cart-side, so I can just make the commands more ad-hoc, depending on what cart is loaded. In this case, telling the cart "I chose this ROM from the menu" is just saving the ROM number to `0xA001` (GB SRAM.) Maybe some kind of ROM-header could also tell the cart "I will need these capabilities" so it will be easier for others to use wifi/bluetooth/i2c without changes to the GB-side cart (just add magic to their ROM-header). I think the "manufacturer" & "licensee" field could be used, if we use one that is not already in use. We might also be able to abuse the "title" field (start with 00, then use the other bytes to communicate capabilities.)

All the menu-paging stuff seems a little fiddly, so I might just try to write the whole file-list into a SAV file (SRAM), so I can manage page-loading GB-side. This would allow me to use a single routine for ROM/RAM and it would be easier to debug (read SAV file on computer.) 8 MB should be more than enough room to store the list of filenames & total length. If I use some known-format that I can seek on the GB (20bytes per name, total-count at beginning of list) I should be able to efficiently do all the menu-paging on the GB, and it'd be easier to manage.

I just got started on the cart-side, but maybe we should work together!

  Are you sure? yes | no

Nick Shvelidze wrote 04/17/2018 at 18:40 point

Hey, I just had a similar idea and was glad to find this. My idea was to integrate an existing flashcart with an ESP and have a ROM that would talk to the ESP and the ESP would handle only networking and downloading ROMs to the flash.

Is this even possible? Seems simpler than emulating the cartridge on the ESP.

  Are you sure? yes | no

greenaum wrote 04/09/2018 at 06:20 point

Non-professional opinion, but this looks really, really, really hard.

Surely what would be much, much easier, would be to stick a SRAM chip in there. Wire it up as a simple ROM from the GB's point of view. Then let your ESP program that, at it's own rate.

Then you could use an I2S expander chip and it wouldn't matter if it was slow.

For contention over the SRAM, have the ESP only write to it when the GB hasn't asserted /CS for a while.

To get it all synced up, perhaps on switch-on have the ESP quickly bung as much code into the SRAM as possible? Including a routine for the GBA to run in a loop from it's onboard RAM for a while. This gives you time, if needed, for the ESP to finish writing to the SRAM. Since your GB software controls where it jumps to, it essentially controls the /CS pin to the cart. That could be how you signal to the ESP that it's time to do some more reading and writing of the SRAM.

It shouldn't be too much of a trick to get them synced up like that. AIUI this would be necessary because there's no way to halt the GB's access to cart memory, a cart is always ready for access. So you'd have to take care of that, fortunately you're writing the GB's code!

Now I think... Since on boot the GB will ask for an opcode, 00 is NOP. So your voltage buffer chips might be hacked to provide that at switchon? Lots of NOPs. Use weak pulldowns maybe, and set the buffer to tristate?

Actually I say wire the SRAM up as ROM... except connect the /WR line too, so GB can write back to SRAM, to send messages to the ESP about button presses and things.

Since it'd only be a 32K simple cart, like Alleyway or the like, you wouldn't, AIUI, need an MBC at all.

OR... you could give up, use the Link port (cables still widely sold), and just buy a commercial GB cart that takes software on SD cards. Thank Chinese pirates and CPLDs for that. So then you just have a lovely slow bit-banged serial bus to talk to.

The way you're going, though, trying to emulate a ROM chip, on the fly, live, in software on an ESP that doesn't have enough pins... no insult to you, mate, but if Sprite or CNLohr managed that, I'd be impressed!



  Are you sure? yes | no

davedarko wrote 04/09/2018 at 07:55 point

I tried not to get angry about this comment. I failed. I'm so not able to accept comments like "try this chip", "use this method instead", "do it like xyz did", "give up" and "you're not one of the chip gods". Sheesh. 

I have a 32Kb cartridge design already. I know where to buy bigger ones as well.

The ESP32 chip has enough pins (def. more than the ESP8266) to emulate a smaller cartridge, you can emulate bigger cartridges with the exact same way the game boy does, write to an address and switch (smaller) banks. That would make it impossible to run "stolen" ROMs, but I wasn't interested in that. The chip itself was fast enough in theory to provide comparable results to the STM32 chip [https://hackaday.com/2014/12/30/game-boy-cartridge-emulator-uses-stm32/]. It was an experiment to see if I can do the same. Turns out I failed on slow setting pins. Talking with SpriteTM about the project on the other days Hackchat he gave me some notes and said it should be possible, but tricky. 

I welcome you to try out your methods and post them here, but please: sometimes it's really not about what you made a chip do, but with what chip you did it. I wanted to see if I can get a one chip - wi-fi cartridge.

  Are you sure? yes | no

greenaum wrote 04/11/2018 at 00:16 point

Ok. I got the impression from this, that you wanted a Wifi Gameboy, so you could travel around Wifiing things with it, and write interesting stuff for the GB to do nifty Wifi tricks and whatever.

But actually this is, for you, more of an experiment in emulating a ROM chip with a micro. Admittedly a very powerful micro.

So you don't want to know about other methods of achieving the result because in this case, your method really IS the result you desire. That's OK. You should probably have said so though.

Obviously Sprite knows what he's talking about here, and he's not sure if it's possible.  I'd take that as a warning that it's going to be incredibly difficult, frustrating, and might well fail. There's easier ways of achieving your stated aim. But now I know, that's not your real aim.

Fair enough. If you manage to make this work, I'll be in the front row applauding, it will be very impressive. Good luck with it!

  Are you sure? yes | no

davedarko wrote 04/11/2018 at 11:54 point

@greenaum I've said that in the "the goal" and "choice of hardware" part of the details, but probably should have added it to the description as well. I'm very aware of the difficulties and frustrations it can bring with it and I threw the towel once or twice :) My skill set definitely isn't that good to accomplish what seemed a good and easy idea at first, but I wanted to share it anyway and see if it is possible and if so, how. 

  Are you sure? yes | no

[deleted]

[this comment has been deleted]

davedarko wrote 05/15/2017 at 07:05 point

Actually not ;) I've integrated a backlight into my Game Boys. Well in 3 of them.

  Are you sure? yes | no

el.seyf wrote 05/14/2017 at 21:33 point

Looks promising, but isnt it more feasible to use the LINK Port instead of the Cartridge Port for the ESP and write some driver to put on a separate cartridge? For cartridge emulation, you might need some kind of parallel DMA that can output 8 Bit on the ESPs GPIO clocked by the Gameboy to make it work somehow, but I havent found any such feature (did a quicksearch, maybe the datasheet reveals something?)

  Are you sure? yes | no

davedarko wrote 05/14/2017 at 21:56 point

The closest thing I've came up with through extensive googling is parallel I2S, that's where my hopes are right now.

There is also this: http://hackaday.com/2016/08/21/fly-with-a-game-boy-classic/ - where the game boy communicates over the serial port with the computer, thanks to a custom cartridge. I do like that approach and think it is feasible to go that route. But it would also require two parts, a cartridge AND an ESP dongle on a port that no one builds plugs for anymore. From a hardware aspect it is much easier to do an egde connector on a pcb and wire up the ESP. 

  Are you sure? yes | no

davedarko wrote 05/14/2017 at 22:09 point

I've added part of my response to the detail section, thank you very much for asking!

  Are you sure? yes | no

haydn jones wrote 05/14/2017 at 21:07 point

Can you do midi over bluetooth/usb with this. would go down with the chip-tunes crowd if it could just work with modern software without loads of mods.

  Are you sure? yes | no

davedarko wrote 05/14/2017 at 22:01 point

"not modding" is definitely a key benefit of having everything on the cartridge, so it would probably be possible. But I have no experience with BT nor MIDI over BT... 

How does the Game Boy even Midi? Also over the serial port?

  Are you sure? yes | no

Frank Buss wrote 05/15/2017 at 08:20 point

It probably doesn't do MIDI. But the idea is to use the Gameboy as a synthesizer, which you can play with MIDI, e.g. controlled by Cubase from a PC, or even from a MIDI piano keyboard.

Obviously you need a program for this on the Gameboy, maybe it already exists. For the C64 there is Cynthcart. Together with my Kerberos Cartridge it can be used to use the C64 as a MIDI instrument, as demonstrated by a beta-tester of my cartridge here:

  Are you sure? yes | no

bamboori wrote 05/14/2017 at 20:59 point

inb4 Gameboy online multiplayer!
Also, have you considered using a Gameboy colour instead? Should be much better for light web browsing (especially when it comes to images).

  Are you sure? yes | no

davedarko wrote 05/14/2017 at 22:04 point

Totally honest: I'm not sure how to do that. I would have to steal the header from a game boy color cartridge and go from there, but for know I'm quite happy if I can get text to work ;)

  Are you sure? yes | no

zakqwy wrote 04/24/2017 at 17:33 point

Gameboy war driving sounds really awesome. Great project! I haven't played around with the esp32 nearly as much as many others on this site, but I agree with your assessment that power consumption may be a concern. Definitely a good application for a lipo retrofit, maybe there's an existing design out there for the GBP so you can focus on the cartridge?

  Are you sure? yes | no

davedarko wrote 04/24/2017 at 17:47 point

thank you for reading the logs and the kind words :) for now I will probably breadboard something together and work from USB power or an external power supply. Maybe a ton of caps can help, I've seen some designs that actually work with a coin cell, given some 1000uF tantals. But yes, the focus is full on the cartridge.

  Are you sure? yes | no

coletonn wrote 04/24/2017 at 00:13 point

Oh crap this is really cool. Ever thought of making a cloud rom storage? So connecting the cartridge to a site, then remotely transferring it to the cartridge. Connecting it the cloud and then pushing a button would save the state and upload it. 

  Are you sure? yes | no

davedarko wrote 04/24/2017 at 07:46 point

I'm still at the "oh crap, I have no idea what I'm doing" stage :)

Right now I'm thinking war driving with a Game Boy, controlling MQTT stuff and browsing http://retro.hackaday.com/  - that kind of stuff. But I will probably start with faking to be the hackaday cartridge I've build in #Game Boy Cartridge plus Programmer project.

  Are you sure? yes | no

Similar Projects

Does this project spark your interest?

Become a member to follow this project and never miss any updates