Ok, so it's kind of a long story but at one time in my life I decided I really really wanted to play games on my computer using an NES controller. This was back in the late 90's, long before usb controllers made this a really easy thing to do.

Step one was to open up a controller and see if I could figure out how it worked. Turns out there was only one IC in there, an SK4021B. A quick look through a friend's dad's Mouser catalog showed that this was a shift register. My friend's dad cut out the schematic for the chip and I took it home. I then taped it to a sheet of graph paper and planned out which of the 8 inputs I wanted to map to each button on the controller. Here is the actual drawing I made:

schematic

full resolution

I choose to use the parallel port on the PC to control things because I knew it had enough pins that I could interact with to power and read from the shift registers of two controllers. You can see on the drawing where I mapped out the pins from the controller to the parallel port adapter. One trip to the hardware store and a few minutes of soldering and taping and I had myself an adapter that I could plug two NES controllers into and adapt them to the parallel port on the computer.

Now, I simply had to figure out how to get the computer to recognize the controllers. I decided it'd be simplest to read the buttons from the controller, map them to keys on the keyboard, and then use the ps/2 IO registers to trick the computer in to thinking those keys had been pressed and released in sync w/ the buttons.

You see, ports 0x60h and 0x64h can be used to directly talk to the ps/2 keyboard on a computer. All I had to do was send 0x62h out to port 0x64h, and then send the keyboard scan code to port 0x60h. The computer would take care of the rest, acting as if those keys had actually been pressed or released on the keyboard.

All that remained was to finish the app that would insert itself into the runtime of BIOS Interrupt 8, check the keypad, emulate any new key statuses it found, and return. Interrupt 8 was called every 50 milliseconds or so, which meant the controller would be polled much faster than I would ever be mashing buttons. Then I opened up my game of choice, set the inputs to the appropriate keyboard keys, and I was playing PC games w/ my NES controller.

A copy of the code I used can be found here. I may try to brush up on my assembler code and walk through it in another post, but for now I think this about covers the broad strokes.