31

I'm looking to buy or make an NES cartridge that can be controlled by a microcontroller or small computer like the Raspberry Pi.

I don't want to gut an NES cart and put an NES emulator inside it (as most of my Google searches are returning), instead I'd like to have complete control over a cartridge that is plugged into a real NES or clone, and have a live interface to the console (through the 72-pin connector) along with a live interface to a PC (serial over USB or Ethernet), and to-be-determined microcontroller and other electronics and firmware sitting between them.

There are plenty of flash cartridges available but they are more like a traditional cartridge where they are written to and then plugged into the console and aren't changed until the console is powered off. Being able to re-write 'ROM' memory locations from a PC through a serial (Arduino) or Ethernet (Pi) connection interleaved with when Nintendo is reading them would be the idea, the game would copy the same sprite or background tile from the same memory address but get something different than a previous cycle (I'll worry about how to synchronize and not be in the middle of a memory copy later).

It looks like the flash cartridges use FPGAs to simulate a ROM, but I wonder if a fast enough microcontroller could write to all 72 pins (or the subset of them that actually matter) every NES cycle – 1.x MHz NES → 1.79 × 72 × margin-factor MHz microcontroller (or less because only a subset of all those pins are needed)?

Minimal cost and open source software and hardware is a big plus.

5
  • 1
    'nes dual port ram' is a promising search, so far I've found batslyadams.com/2014/05/nes-dual-port-ram-interface.html but it doesn't go through the cartridge port, and isn't open source. Commented Mar 29, 2017 at 20:18
  • Dual port ram is also very expensive.
    – cbmeeks
    Commented Mar 29, 2017 at 20:20
  • I'm seeing a lot of nes fpga github projects github.com/search?utf8=%E2%9C%93&q=nes+fpga&type= (probably in various states of completion and/or abandonment, and particular to a specific fpga dev board), but they are only on the console side rather than cartridge. Commented Mar 29, 2017 at 20:24
  • Is retro-computing the appropriate place for Arduino, PI or other micro-controller development solutions?
    – jwzumwalt
    Commented Jun 2, 2018 at 22:36
  • @jwzumwalt This seems to come under new-hardware-adaptation. I'll leave this in the queues for a bit.
    – wizzwizz4
    Commented Jun 3, 2018 at 8:54

9 Answers 9

23

As cbmeeks said, you're much better off with a FPGA or CPLD. It's going to be nearly impossible to emulate an NES ROM with a microcontroller. A Raspberry Pi would be fast enough, but not with an operating system.

It's possible to run code directly on a Raspberry Pi without an OS, like a microcontroller. You don't even need to worry about cycle timing to emulate a NES rom; you can rely on the M2 signal to know when to read the value on the bus. You're going to run out of I/O pins -- the Raspberry Pi only has 26 -- but you can reuse pins with shift registers. If you only want to emulate NROM games, you could use two Pis -- one for the CPU address space and one for the PPU (and maybe the CIC chip too, since you'll have a couple of spare pins.)

Another option might be something from the BeagleBoard family, such as the BeagleBone Black. These normally run Linux, like the Raspberry Pi, but it seems like it's easier to use them without an OS. The BeagleBone Black doesn't have enough GPIOs even for just the CPU, but you can always use shift registers, and you might be able to repurpose some of the other pins, especially if you're running without an OS.

12
  • Couldn't you use an external multiplexer to access more pins? Commented Mar 29, 2017 at 18:29
  • @StephenKitt Yes. I mentioned that briefly, but I didn't discuss it as much as it deserves.
    – NobodyNada
    Commented Mar 29, 2017 at 18:42
  • Ah yes, sorry, I'd noticed you'd mentioned latches but somehow skipped the multiplexers. Commented Mar 29, 2017 at 18:54
  • Multiplexers aren't going to give you more pins. Shift registers are for that usually. For example, the 74138 has 3 input pins (not counting control pins) that control 8 output pins but you can't select output pins 1,3 and 7, for example.
    – cbmeeks
    Commented Mar 29, 2017 at 19:14
  • @cbmeeks Right, but the multiplexers can be used for inputs (or is that demultiplexers?).
    – NobodyNada
    Commented Mar 29, 2017 at 19:22
13

I doubt you're going to be able to pull that off with a micro-controller. Maybe one of the 200-300 MHz versions...maybe....but unless you try a Teensy 3.6, you may also have to design your own board for the mcu too.

Anyway, the problem is that you can't compare MHz to MHz like that. Just because the NES ran a 1.79 MHz and MCU "A" runs at 200 MHz doesn't mean it's 50 times faster. The CPU's in the micro-controllers need so many cycles of the clock to execute even one instructions.

Take, for example, the Propeller MCU from Parallax. It runs normally at 80 MHz. However, it takes 4 cycles to do pretty much anything with it. So the effective throughput is closer to 20 MHz. So, that roughly means that within the time it takes the 6502 on the NES to execute one instruction, the Propeller can execute about 10. And that's very lenient and high-level.

There just isn't much you can do with 10 instructions. Grab a few registers, update a value, etc. Not much.

The Raspberry Pi may have better luck because it can run past 1 GHz.

HOWEVER, the problem with the RPi (and any computer) is the OS. The OS will not (and CANNOT) guarantee you the cycle access that you need. It's nearly impossible to count cycles on them. This is true of Windows and Mac too. Like I said, you might be able to get away with it but there's going to be a huge margin of error.

Another issue is voltage translation. Many fast micro-controllers cannot operate with the 5 volts the NES requires. So you have to level-convert the voltage. Which has propagation delays too that have to be accounted for.

For what you're describing, I would recommend a low-end FPGA or maybe even a CPLD. You can still find CPLD's in a PLCC84 package (easy to work with while prototyping) from Mouser that tolerate 5V and are as fast as 5-10ns. Plus, you get the TRUE parallelism they provide.

I don't want to discourage you. But, you should know what you're asking seems pretty difficult if you're a beginner.

2
  • 1
    The Raspberry Pi doesn't need an operating system to run. If you're feeling crazy, you could bootstrap your own low-level code off the GPU. If you're feeling lazy, you could just tell the GPU bootstrapper to run your code on the CPU instead of the Linux kernel.
    – wizzwizz4
    Commented Jun 4, 2018 at 16:02
  • 1
    A 70MHz ARM7-TDMI with enough I/O pins to accommodate the address and data buses is sufficient to emulate an Atari 2600 cartridge--even a complicated one like the DPC (David Patrick Crane) chip found in Pitfall II. The NES may require a somewhat faster chip, but probably nothing too crazy.
    – supercat
    Commented Jun 4, 2018 at 22:48
10

Your stated requirements are for hard real-time read/write access to all the pins. But for homebrew development, all you really need is to be able to interactively read from and write to ROM and RAM and the CPU registers. There's a flash cart called the EverDrive N8 which lets you add a USB port for debugging. But I don't think the debugging software exists for it yet, just some drivers and source code at the first link above, so you will need to integrate that with gdb or whatever you decide to use. You may also need to work with the author to add any features to the flash cart's FPGA (an Altera Cyclone II) that you need for debugging. Good luck!

3
  • 6
    This doesn't answer the question asked, but it solves the problem. Unfortunately the OP already talked about flash carts in the question so presumably knows about this solution. Thanks for the answer though; it would help other people.
    – wizzwizz4
    Commented Mar 29, 2017 at 19:09
  • @wizzwizz4 Well it solves half of the problem, the hardware half. All that's left is the software side and maybe some FPGA support. Commented Mar 29, 2017 at 20:31
  • 1
    @wizzwizz4 I think this sort of approach is more practical. The use-case sounds like a hosted debugger for an embedded system to me. Maybe it's possible to just add JTAG to the NES?
    – Brian H
    Commented Mar 29, 2017 at 21:00
5

When I did some hard embedded work about 20 years ago, we have a set of 'EPROM Emulators'. Basically, it was a set of rams that plugged into our system in place of the system's eproms. You'd hold the system into reset, change the contents of the rams (serial link to a PC, took a second or three), and then let it run.

Worked beautifully for what it was. You can't really change the code mid-run, but frankly you're going to have trouble making that happen without crashing things anyway, so not being able to do it isn't really costing you much.

They are still available, but kind of pricey. I'd try to either pick up an old one, or make my own (you don't need much ram). You'd need to sacrifice a cart, but that shouldn't be too hard, and you could easily use a Pi as a the brains of the thing (When not loading the RAM, just make sure that the Pi's control lines to the RAM are tri-stated.)

5

'Making of "Reverse emulating the NES..."' video on youtube (from tom7/suckerpinch) demonstrates the Raspberry Pi route working with additional chips and hackery to make the timing mostly work, but is glitchy.

One of the tricks involved not being able to actually deliver the correct memory from the Pi in time to a read request, it would arrive a cycle late. But the read requests are predictable given that the application software is also custom, and the entire NES can be emulated in the Pi while a real NES is running.

3
  • 1
    This answer would be more useful if you added some more information; link-only answers aren't too useful. What if that YouTube video gets taken down?
    – wizzwizz4
    Commented Jun 4, 2018 at 16:07
  • I'll take some notes next time I watch it and flesh it out, otherwise anyone else could sooner and edit my answer, or make their own and I'd vote for their answer over mine. Commented Jun 4, 2018 at 22:28
  • I found a blog post on this.
    – wizzwizz4
    Commented Sep 7, 2022 at 18:23
4

As I understood, you want to make something that behaves like any possible NES cartridge and can be changed (at least for simulated ROM content) on the fly (in real time)?

And it should be cheap and open source?

Quick Answer: Dream On


The Full Monty

What you're asking for is something like test equipment for chip manufacturing. There are units that would satisfy sour requirements and speed - but they are neither open source, nor cheap - think 100k EUR for entry level. More important, none will fit in a NES cartridge.

Of course such a beast would be able to not only react to all your needed transfers in time but also emulate next to any special circuitry.

Lets Shovel

It's a matter of speed (and memory). You already touch on this with your rough numbers

(1.x MHz NES -> 1.79 * 72 * margin-factor MHz microcontroller? Or less because only a subset of all those pins are needed)

That would give some 128 Mbit/s (or 8 MByte). Except, that's only if all data is prepared in sequence or requests. In reality, the CPU sets up a request and wants a reaction within less than 200ns. So even when only looking at the data lines, it needs to transfer 72 bit to the emulation thingy, and 8 bit back all within 200 ns, cranking the needed connection up to ~800 Mbit/s.

Just to transfer the data we are already near a PCIe 1.1 line not counting the overhead - and with no necessary processing on the PC side included. Not to mention all the various latencies a PC may have to feed the data in time.

The fastest Pi Network is Gbit with the Pi 3 B+. So that alone wouldn't make it. Also a Pi wouldn't be able to do it locally.

A Smaller Size

Well, if we ignore all special hardware cartridges and go just for something with ROM and the ability to change that data at runtime, the picture becomes very different. One could use some dual port RAM and a microcontroller. One side connected to the NES interface, maybe with the usual banking logic added, while the other side can be filled (or read) from said microcontroller.

To the NES this looks like a perfectly normal ROM cartridge, even (simple) RAM as with Super Mario Bros 3 can be done. From the PC side, each cell can be read or written.

Of course, it's again a matter of speed. But now it depends more on the amount of data you want/need to change within a certain time. This again depends on the programs you want to write. A high speed USB 2.0 will already be able to deliver data faster than the NES can read it - as long as it's semi streamed, not totally random.

In fact, if the data is read from only a few cells in sequence under program control even a USB 1.1 full speed can do the trick, as even with the fastest access a 6502 needs 4 clocks to read a single byte (LDA <ABS>), and many more if it's doing something with the data. This turns the needed bandwidth down to less than 500 KiB/s - USB 1.1 full speed can deliver up to 1 MiB/s.

With some thought it might be possible to write a low overhead protocol to deliver your data just in time.

And no, Dual Port RAMs aren't overly expensive. 1 Mib (like in 128Kib x8) is around 30 Euro per piece. For a one off design, chip prices do not really matter in comparison to the time invested.

The Gist of the Matter

The game would copy the same sprite or background tile from the same memory address but get something different than a previous cycle.

Hmm, when reading this, it sounds as a single pipe could also do the trick?

So why not doing some more common FLASH based ROM emulator (maybe with a Arduino for reload without unplugging) and a FTDI FT232x based USB-FIFO? From the NES side this could look like a single memory location delivering a new byte each time it is accessed, while the PC sees a high speed serial connection. The internal buffer of up to 2 KiB would cover next to all possible timing issues. And the back channel could be used to send commands to the PC.

In Lockstep

(I'll worry about how to synchronize and not be in the middle of a memory copy later)

Synchronizing the game to the USB clock would make a great start.

3
  • Naive spitballing: if the entire 6502 bus is exposed on the cartridge connector, couldn't one run a 6502 emulator in parallel in order to get foresight of relevant upcoming reads and writes before they're announced, buying extra response time? Like if you see the 6502 consume the bytes for LDA $addr then you don't need to sit idle through the next phase 1 thinking "oh, I wonder what the 6502 will ask for next", you can do whatever processing is necessary to cue up the proper value for $addr during phase 1 and have it ready to go by phase 2. Too naive for words?
    – Tommy
    Commented Nov 27, 2018 at 15:07
  • 1
    @Tommy Sure, it'll extend the period to retreive the byte from something like 300ns to 900ns (or so), which is a big increase on a cycle level. Then again, not realy much more when considering a round trip to the PC and back in real time. The advantage of the streaming access would be to not relay on the access cycle, but rather optimize on instruction level, so instead of serving a byte within 300 (or 900) ns, we got 2000ns (or more).
    – Raffzahn
    Commented Nov 27, 2018 at 15:50
  • @Raffzahn that makes a lot of sense; all you have to do is spot the SYNC, check the accessed address, confirm its one you are serving, and you can plan out most or hopefully all of the work you'll need to do for the next few cycles. If the PC is starting the opcode at $8000 then, as you say, if you look at what you're serving at $8000 and it's a LDA that'll end up hitting a memory-mapped device, you've then the entire length of the opcode to come up with the result. Somehow I was too stupid to realise I was suggesting what you already suggested. Thanks for clearing that up!
    – Tommy
    Commented Nov 27, 2018 at 16:49
3

I agree with other answers that this is not a trivial task but it's actually doable.

Here are the examples of such a project :

4
  • How different are the specs of those boards than an Arduino or Raspberry Pi? Are they comparable?
    – JAL
    Commented Apr 5, 2017 at 20:41
  • Raspberry pi has more processing power. I'm not very familiar but it's possible to use it without an OS to achieve fast GPIO handling. Sure there are few I/O pins for such a task but one can always use parallel load serial out shift registers to gain more GPIO. Both 3.3v systems so in some signals level shifting is inevitable. Personally I would prefer a microcontroller with an arm core. The hardest part is in syncing with the bus of the host system. Otherwise everything else is much simple to implement compared to a FPGA/CPLD solution.
    – Nejat76
    Commented Apr 5, 2017 at 20:52
  • @JAL: Most general-purpose computing devices use cached memory systems whose average access times are very good, but whose worst-case access times are much worse. This allows average performance to be a couple of orders of magnitude better than the NXP chip used in the Harmony cartridge. On the other hand, almost any time the 2600 tries to read or write an address, it will be absolutely imperative that the ARM respond to that action within about 0.7 microseconds worst-case. On the NXP, it's easy to compute worst-case times and ensure that they won't prevent timing goals from being met.
    – supercat
    Commented Apr 20, 2019 at 16:46
  • @JAL: On something like the Raspberry Pi's processor, however, code that might take anywhere from 0.56 microseconds to 0.62 microseconds on the Harmony's NXP chip could have a time that could vary anywhere from 0.05 microseconds to 1.05 microseconds depending upon memory caching issues, even if one were running on "bare metal" with the operating system disabled. If the operation were to take 0.05 microseconds 99.999% of the time but 1.05us the other 0.001%, the average time would be faster than the Harmony's NXP, but about ten memory fetches per second would yield bogus data.
    – supercat
    Commented Apr 20, 2019 at 16:50
1

In this project called PiPU, someone has already done similar to what you want to do with the Pi and the source code is available: https://github.com/rasteri/PiPU

You could also use the EverDrive N8 PRO Cartridge which already has a USB port. You could connect your Pi to this or examine the flash card to find out how this was solved here: https://krikzz.com/store/home/57-n8-pro.html

Someone here has built a NES-to-USB cartridge that you can be inspired by, maybe the author is already willing to make his work available, maybe just ask, I would also be interested. But either way, his article gives some ideas on how this could be done: https://troydenton.ca/?p=260

A similar project with an FPGA and a Beagle bone, again his work is available on Github: https://github.com/astoria-d/super-duper-nes

Here you can learn how to build your own NES cartridge: https://thepoorstudenthobbyist.com/2017/06/25/how-to-make-an-nes-reproduction-cartridge/

This PCB for prototyping NES cartridge board might also be helpful: https://github.com/Redherring32/NES-ProtoCart

0

I am not that familiar with the NES system architecture, but what you are asking is possible for the Commodore 64. You can check details of the IrqHack64 cartridge on Lemon 64

This cartridge monitors the system for the IRQ signal. When it happens it halts the CPU and injects the required data into system ram. If the NES allows cartridges to halt the CPU, you can do a similar trick. In this case you might consider RAM chips instead of cartridge ROM.

5
  • 2
    Unfortunately, that's not going to work for the NES. The NES cartridge is memory-mapped directly into the address space, so the NES must be able to access the PRG-ROM at the full CPU clock rate (about 1.7 MHz), and the CHR-ROM at about 2.5 MHz (half the PPU clock rate).
    – NobodyNada
    Commented Mar 31, 2017 at 16:55
  • I think C64 cartridges are also memory mapped directly into address space (subject to banking), it's just normal for things to run from RAM rather than from cartridge because most things don't come on cartridge.
    – Tommy
    Commented Nov 27, 2018 at 15:10
  • @Tommy: You are correct. C64 cartridges are 'generally' memory mapped but what I've described above is a special utility cartridge, which is not memory mapped except the I/O register.
    – wizofwor
    Commented Nov 28, 2018 at 6:00
  • If one wants to perform emulation in a way that works with existing cartridges, timing constraints will be quite tight, but if one wants to design a game around the microcontroller in the cart, timing constraints could be much looser. For example, even if the microcontroller had only the "cartridge ROM enable" signal, it could respond to all cartridge bus cycles with $85 (sta zero page) until it saw a sufficiently-long sequence of two cartridge cycles followed by a non-cartridge cycle that it could determine that the CPU had reset and was running code. At that point...
    – supercat
    Commented Apr 28, 2020 at 21:09
  • ...the micro could start responding to cartridges accesses with data read consecutively from a table, which would represent an instruction sequence to store some code into RAM and run it. After that, microcontroller could simply ignore the main CPU bus if the code in RAM was set up to communicate with it via the PPU buses.
    – supercat
    Commented Apr 28, 2020 at 21:12

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .