Bringing old things back to life holds a great sense of joy for most people. The never ending pursuit of recapturing our youth leads us down roads we’ve long forgotten. Along the way, we tend to bump into forgotten memories which jostle other forgotten memories which allows us to relive happy times we haven’t thought of in years, sometimes even decades. For some, the roar of a 351 small block sweeps them back to high school and the fast nights of cruising down main street with the FM radio cranked up as high as it would go. For those of us who were born in the 80’s and 90’s, video games can bring back such memories. Who among us can forget our first encounter with Link, the elegant theme music of Final Fantasy or up-up-down-down-left-right-left-right-b-a-select-start?
Advances in processor technology has allowed us to relive our favorite games via emulators – programs that emulate processors of older computers. The games are ‘dumped’ from the ROM chips (where they are stored) into files. These game files can then be loaded into the emulator program, which allows you to play the game as if you were playing it on the original system.
Technology is truly a beautiful thing. It allows us to move forward, allows us to do today that which was not possible yesterday. There are a few cases, however, where this paradigm does not hold true. One of these has to do with the Nintendo Entertainment System and its “Zapper” gun controller. The NES was the most popular game console of its time, and rightfully so. From the minds of Nintendo engineers, programmers and audio experts came some of the best video games ever made. Unfortunately, some of these great games cannot be played on your
Raspberry Pi favorite emulator due to the incompatibility of the Zapper gun and modern digital monitors. None of us can forget the fun that Duckhunt brought. The game came as standard issue with all NES systems, so we’ve all played it. But its nostalgia is currently entombed by a technological quirk that has yet to be solved.
From one hacker to another – this can no longer be tolerated. First, we’re going to learn how the Zapper works and why it doesn’t work with digital displays. Then we’re going to fix it.
The Zapper gun is basically a photodiode and a switch. When the trigger (switch) is pulled, the NES does something to the screen to determine where the gun is pointed. What this something is will be discussed in a bit. But first, we must understand that it only works on a CRT analog television. Plug your emulator setup into one of these, and you will have no issues. The problem is that nobody has CRT televisions anymore. Everyone has digital flat screen televisions and monitors. Plug your setup into one of these, and it doesn’t work. We need to understand why this is.
Putting A Myth to Rest
There seems to be a lot of confusion about how the NES knows where the Zapper is pointed on the screen, even among electronic types who should know better. Some people seem to think, and continue to put forth the myth, that the NES looks at the scan lines on the CRT. A CRT draws scan lines from the top of the screen to the bottom in a certain time interval. By looking at the time between the start of a scan and the time the Zapper sees the scan, the NES can know where the Zapper is pointed. And because a digital monitor will show all scan lines simultaneously, there is no way for it to calculate where the Zapper is pointed. This might be true of some other types of photodiode based guns, but it is not how the NES works. Not even close.
How the NES Zapper Works
It’s pretty clever, actually. When the trigger is pulled, the NES will write a blank, solid black frame to the TV (more on this later). The NES outputs at 60 frames per second, so a single frame will last 0.0166 seconds or roughly 16ms. The next frame will put a white rectangular box around the target duck, with the background remaining black. At the same time, it polls the state of the photodiode in the Zapper. There is a measurable difference in the output of the photodiode when pointed at a black part of the screen versus the white box. And this all happens in only two frames, or ~32ms. You can barely notice it. The following frame goes back to the game and records your shot as a hit or miss. Brilliant!
“But wait, how does it work when there are two targets?” Good question. The NES engineers dealt with this issue by doing the exact same thing, just twice. So you would get the solid black frame, then the next frame would paint a white box over one target and poll the photodiode, just like if there was only one target. If there is another target, the third frame will just put the white box over the second target. The three frames happen in about half a second, so you don’t have time to shoot both. You can only shoot one, and this technique allows the NES to know which one you shot.
“If the NES is just looking at the state of the photodiode, can I just point my gun at a bright light and score a hit every time?” This is another good question. The NES engineers took this cheat away by first writing a black screen and looking at the state of the photodiode, ensuring this would not be allowed. If it sees anything other than the black screen, it will record the shot as a miss. It is rumored that some very early versions of the game might not have had this bug fixed, but there has been no demonstration of such a bug to date.
Another Look At The Problem
Now that we know how the Zapper actually works, we can move on to a resolution for the digital monitor issue. If all it’s looking at is the white/black contrast, it should work just fine on a digital monitor. But it obviously doesn’t. There are some that say the photodiode is sensitive to IR from the CRT, and a digital monitor does not give off any IR. But take a look at this 12 second video. The zapper seems to work just fine!
We know the scan line argument is rubbish and the Zapper can discern the white/black contrast on a digital screen. We can only conclude that our issue is timing related. It appears that an analog CRT can write an image to the screen much faster than its digital counterpart. The NES is hardcoded to look for the white box after 16ms has elapsed. If our digital screen is unable to process the output of the NES fast enough, it will be looking for a white box while the normal game screen is showing.
The output resolution of the NES is 256 x 240. A digital monitor would have to process each frame to scale it up to its set resolution. This process introduces a lag which can reach up to 70 ms, well beyond our 16ms frame rate.
How To Fix It
Well, it won’t be easy. If a digital monitor is, by its nature, too slow, the only resolution is to slow down the NES.
Option 1 – Underclocking
We’ve all heard about overclocking. But what about underclocking? Could we slow down time in the NES processor without accelerating it to a percentage of light speed? It would have to be done without locking it up of course. It would need to run at normal speed, but when the trigger is depressed, we would need to switch over to a lower clock speed and effectively lengthen the delay times. Remember, the NES writes a black screen, delays for 16 ms, and writes the white box. By slowing down the processor, we can lengthen that delay and give the digital monitor time to catch up.
Option 2 – Edit the ROM
The only real way to edit a ROM is with a hex editor. What if we could single step an emulator and find the piece of data that represents the delay after the trigger is pulled? If we could find it, we could just make it longer and hope it doesn’t break anything.
Option 3 – Your Turn
Now that you know exactly how the NES Zapper works, and exactly why it can not work with a modern digital monitor, you are well on your way to solving the problem and freeing the nostalgia that a cruel twist of technological fate has locked away from our generation. What would you do to make the Zapper work with a digital monitor and become an instant internet hero?
This is not a complicated setup. Surely we can put our heads together and get the Zapper to stop firing blanks at our digital world. Let us know your solution to this problem in the comments below.