Monday, May 5, 2014

NES Dual Port RAM Interface

UPDATE : Thanks for the great response - I'll be posting more videos throughout the week @batslyadams - I'd love to hear your ideas for ways to enhance games! Looking to livestream some development / testing this Thursday, 5/6/14.

I've been writing a game recently and was looking for a way to live debug on real hardware. The original solution was to fire variable information out the second controller port to serial every NMI but I decided to to take a shot at a new PCB for the console I've been dreaming about for a while.

The board routes the left port of the dual port RAM (Cypress CY7C136) to the DIP footprint on the NES and the right port to an AVR (ATMEGA164), this allows me to read and write any location at runtime without bus conflicts. Control is provided through the UART and two additional pins are soldered directly to the 2A03 to control /NMI and /RESET. I took a console and desoldered the 2KB RAM and replaced it with a socket. I'd like to permanently solder this in now that they work but having them removable for debugging was a huge help. AVR control code was written mainly in C with some assembly sprinkled across for the memory control portions.

The AVR sits and wait for serial commands and can perform several functions including :
* Read / write of any memory location
* Quick dump of an entire 256-byte page
* Freezing of memory addresses (rewriting a single value constantly in the busy loop)
* Single frame stepping by controlling the NMI
* Remote reset of console
* Applying auto increment to tables to a single variable (fun for sine waves on x/y positions!)

I had pretty great results with using 250000 baud with the Genesis flasher project which is plenty fast for what I'm trying to do here. Cautionary tale about using this dual port RAM part, be sure to operate the other side normally even though it appears to be decoupled. As far as I can tell from the datasheet leaving CE low shouldn't have an effect on the opposite port but it most certainly does. Next revision could definitely use a few pullups on the AVR side, other than that I'm pretty happy with the layout.

Before wiring up the additional control lines :

Pretty excited to finally use this guy - your usual USB FTDI cable except with a 3.5mm jack. Routed the UART to a standard panel mount TRS on the back of the console.

It has been a blast playing with this thing - stuff I've done so far :

Debug Information
The original intention of this was be able to manipulate values in real time on a console for a game I've been developing, FCEUX is pretty incredible for emulation but I try to do a lot of testing on real hardware.

Blades of Steel used to be my favorite, but I'm starting to come around on Ice Hockey. Heavily using the read function to pull any relevant data from a game then deciding what to do with it.
Would probably be great for automatic splits for speedruns.

Relay Control
Contra has a particular way of allocating shots, there are five slots for one player that a bullet can accommodate. I didn't want to cheap out and just trigger on a button press so all five values are pulled and checked for a new rising edge.

Hex editor
Wrote a live hex editor inspired by FCEUX, lots of fun goofing with variables on the fly. Great fun to have a "co-pilot" looking for ways to help you cheat, like a manual game genie.

Single Frame Step
The /NMI pin is the 60hz interrupt generated from the PPU, this is one of the trickiest parts of the NES since this is the only safe window in which to make writes to VRAM. Due to the limited video bandwidth, the game is typically laid out the following way :

Busy loop / Wait for NMI
Falling edge of NMI / Perform VRAM updates then set flag that NMI has occured
Return from NMI / Perform logic updates / queue VRAM updates

On a "step" command sent from the host the AVR waits until the natural falling edge /NMI then asserts low until it receives the command for another step. This safely inhibits the interrupt and keeps everything in sync. Could also set up a frame level breakpoint here!


Enhanced Rules / Displays
Every game needs a place to store the controller reads after a $4016/$4017 fetch. Typically these routines will still run in a pause menu (so you'll know when to exit). The idea is that the host can read that we are in a pause state AND the controller data you can control a menu offscreen.

Remote Reset
I provided two pins for the NMI and RESET on the console, these are jumpered from the 2A03 directly to GPIO on the AVR. Both of these inputs to the CPU are open drain.

The /RESET pin allows you to command a console reset the host so you wouldn't have to fuss with the console. You can provide an argument for a short reset (10ms) to jump to reset vector within the game and a long reset (~1s) which will bring you back to the powerpak menu.

Glitch Roulette
This was a lot of fun. The idea that every time the player jumps (memory location / method of determining jumping will vary from game to game) the host will write a random value to a random location. The sound engine is usually the first to go since they typically require a good amount of RAM and are overwriting is fairly harmless. A hit on an indirect memory address/stack is usually catastrophic.

Biggest ups to Todd Bailey for the help with assembling these things and Adam Stankiewicz and Nick Gargiulo for tirelessly testing blades of steel.


  1. It's amazing, you can now write a kinect based game for nes ;)

  2. I've been wanting to do this for a pinball scoreboard, using the same dual port ram chip. Do you happen to have a schematic/KiCAD files online anywhere? If not it's great to see that the idea is at least sound.


  3. This is incredible! We've been looking for something like this. We play a TON of Blades at our office, and have even built a scorekeeper app:

    It relies on hand-fed data though, and doesn't have any of the more advanced stats direct data would provide.

  4. Awesome! I've been wanting to do something like this for the last 6 months or so. I was borrowing an fpga from a friend, that I was going to program to emulate the memory chip, but this is so much easier. Any chance you'll open source the AVR code?

  5. This is awesome. Exactly what I was looking to do -- grab values during runtime. I wanted to get them, then post to an online leaderboard.

  6. the big bang broderie Replica Watches Anglais, Bischoff, home to see the acquisition of major cooperative Mimi handbag replica ace, and 11 and Diamond Bezel contains a pattern of straps soft.Raffaelli before Ambassador, Kobe Bryant, Jay · Z, Replica handbags her footprints, including the bolt and Wade, to follow, she will attend today to the latest (maximum) Hublot flagship Replica watches UK store at 743 Fifth Avenue Surprise. (This NYFW is your schedule to add another NBA events.) Rolex Daytona .

  7. Great to see that someone still understand how to create an awesome blog. The blog is genuinely impressive in all aspects.
    judi poker

  8. The price of excellence is discipline; the cost of mediocrity is disappointment - William Arthur Ward

    Judi Casino
    Judi Casino Online
    Agen Casino
    Dragon Tiger
    Jadwal Bola

  9. very nice and interesting

  10. Information That Is Very Helpful and very complete, thanks for the news Greetings Dwi ^^

    Togel Online
    Agen Casino Online
    Prediksi Togel Singapura