Basic operation is very simple. On powerup, the cartridge ROM is disabled, and CopyNES' internal 8K ROM is
switched into 8000-FFFF. This allows stealing of the interrupt vectors. CopyNES' ROM is mapped into the NES'
address space at 1000-1FFF and 3000-3FFF. Using this normally "occupied" space was done so the ROM data
would not interfere with any known cartridge bankswitching, RAM, PPU, CPU registers, etc.
Once CopyNES is started, the "stolen" vectors point to the 1xxx area of memory which holds the basic startup
code. The first thing that is done is to re-enable the cartridge. This is accomplished by writing to the port chip. (See schematic, below)
Once this is done CopyNES then checks the status of one of the parallel port lines. Its state determines if we are in "copy" or "play"
Play mode: CopyNES will play the cartridge that is inserted into the unit like normal. It will in all respects be a standard old grey box
NES. All of CopyNES' ROM and port chip will be disabled perminantly until power is cycled, or until the reset button is pushed. once
in "play" mode, that's it. If you do not have the Parallel Port cable installed, CopyNES defaults to play mode.
Copy mode: CopyNES will now be in slave mode, awaiting instructions from the PC via the parallel port.
Back to the hardware description. A 74157 was used to gate A12-A15 to the rest of the NES, along with an OR gate which gates A11.
When in copy mode, this 74157 is used to "shut off" the rest of the NES (and any plugged in carts) so that CopyNES' ROM or port chip
can have the bus, without interference from the PPU, cart, RAM chip, etc. During these accesses, the NES sees 4800-4FFF only.
A 74138 is used to decode the upper address lines to net us 1000-1FFF, 3000-3FFF, and 4000-4FFF. The latter is run to the port chip
which also uses A11 to map it in at 4800-4FFF. One of the I/O lines from the port chip runs up to the enable on the 74138 directly.
When the NES is reset, the port chip's pins are all turned into inputs so the 4.7K resistor pulls the line up to the 74138 so it will be
high when the system comes up (and hence, enabled). If a 0 is written to this port bit (and the port is set to an output), the decoder will
be disabled. Without it, all address decoding ceases, and hence the port chip can no longer re-enable it.
Another output is used to enable the cartridge space over-ride for when CopyNES starts up. It operates in a similar fashion to the above,
however, it does not affect the 74138's decoding and can be turned on and off at will. During startup, it too is pulled up with a 4.7K
resistor so that the cartridge over-ride will occur. The port bit is gated with A15 through a NAND gate, which is then fed into another NAND
gate along with decoded outputs from the 74138 for CopyNES' ROM. If either 1000-1FFF, 3000-3FFF, or (when enabled by the port chip)
8000-FFFF are selected by the processor, the NES section is disabled and the ROM is put on the bus. One last NAND gate was used to
make the ROM "act nice" by only allowing it to be enabled when M2 and R/W are both high.
The remainder of the port chip's I/O lines are used to interface with the PC and the LCD display. The LCD display is a simple Hitachi-style
controller version which can be picked up very cheaply at any surplus electronics store or catalog. Typical cost is $5 to $10. I used a
16*1 character display, but you can use anything you have. The LCD's R/W is tied to ground to put it in write mode all the time.
Note that if the PC's parallel port is in output mode, you cannot write to the LCD (since the port chip doesn't have enough "oomph" to
overpower the PC, even with the 160 ohm resistors). Fortunately, this has never been a problem.
CopyNES is even fairly simple from a software standpoint. I wrote the host code in QBASIC (yeah, don't laugh! :-) and it isn't too shabby on
this PC (Celeron 300a). CopyNES itself has all its code written in 6502 ASM of course. I developed the code on two PC's at once using an
EPROM emulator for CopyNES. Once the code was "blessed", I burned it to an EPROM. CopyNES' code has several things on it other than
just the raw interface. It has a CRC-32 routine (for figuring out ROM sizes when it would be tough to do a side-by-side ROM bank comparison),
and the NSF player, along with a few stock routines such as loading the PPU address, checking for the existance of WRAM, etc.
CopyNES' real advantage is the plugins it uses. These are simply 1K worth of data that sit at 0400-07FF in the NES' standard 2K of RAM.
When you go to read a cart, the PC host software will reset the NES, download the plugin, then execute it. The plugin then takes over and
does all ROM size calculation, mirroring check, WRAM checking, and anything else that needs to be done. I have written plugins for every
type of cart I own. The PC host software has a menu thingy that lets you select what you want to do (read a cart, play an NSF, etc).
On the cart reading portion, you then select what type of cart it is by board number and then enter a filename. Once you do that, it will
do the rest. The output is a fully-formed .NES (and coming soon, .UNIF) file ready for use! No mirroring screwups, no doubled-up ROMs,
etc. And since this is a fully-functional NES, you can test the cart after you insert it *before* you copy to make sure it's in right! This should
eliminate all bad cart reads.
So far, I've made a simple 32K/8K RAM cart that allows the testing of code. This is nothing more than a Super Mario Bros. board that has
had its ROMs removed and RAMs installed, with some very minor re-wiring. It fits back into its cart case since it does not need sockets,
and therefore no holes drilled in the case. Since it's RAM, it needs no (E)EPROM programmer or anything like that. The cart stays in the NES
and after the data is loaded, it is automatically run. Total time is under 15-20 seconds to load up a complete 32K+8K ROM and play it!
The other add-on is an NSF cart. This is a 128K RAM cart with the standard NSF-style 5FFx bankswitching, as well as RAM at 6000-7FFF.
I heavily modified a dead zelda 2 board. I'm not too proud of how I wired it up- chips soldered under the chips soldered to the board, chips
dangling on wires, etc :-). However, it fit back into a standard cart case, and more importantly, *it works*. I have tested all the NSFs in the NSF
collection on it and fixed all the ones that didn't work on it. I will post a schematic of this once I draw and scan one in.
The Good Stuff
Here is CopyNES' schematic. I drew it up and scanned it in :-). Beats using the computer. Notes: I made a special adaptor that is soldered
into the place where the NES processor sits on the main board. This adaptor has a socket on the top where the processor then plugs, and a
ribbon cable (34 pins, I chopped up an old floppy cable!) attached to it which then runs to the add-on board which houses the port chip, EPROM,
and the logic chips. I used the bottom half of an IDC connector (the part with the pins only) and a standard 40 pin DIP socket. I soldered the pins
of the socket directly to the tops of the IDC connector where the wire would normally go. I soldered all pins in this fashion except A11-A15 since
these are run to the add-on board and then back to the rest of the NES. After this was done, I attached the ribbon cable to A0-A10 (which goes to
both the add-on board and the NES), A11-A15 (NES processor only), A11-A15 (NES board only), D0-D7, R/W, M2, /RESET, ground, and 5V. That's
34 wires. After this was done and verified working, I potted (completely coated) the whole mess in hot melt glue. The hot-melt seals and holds
everything together so it will not move, break, or otherwise cause trouble. Heck, it doesn't even look too bad! It looks basically like this white
block of plastic with a socket on top, pins on the bottom, and a wire poking out the side :-). I soldered this adaptor directly to the NES board since
there would not be enough height clearance otherwise (read: the top of the CPU hit the bottom of the plastic NES case). Other than the adaptor,
the rest of this circuit is very easy. Note that I left A0-A10, D0-D7, and R/W, /RESET, M2, and a couple other things off of the port chip and other
stuff. This is because A0 always goes to A0 on everything, A1 always goes to A1 on everything, etc. Putting them all on would've made for a
hard to read schematic. Also, don't forget to add in bypass caps very close to the power pins on every chip. These and power lines were not