PPUdigitizer (for NES) - c0pperdragon/LumaCode GitHub Wiki

The PPUdigitizer is a small modification board for the NES game console. It will passively listen to the data transfer between the PPU and the rest of the system and reconstructs the screen information in a semi-digital form. This can be upscaled with a Lumacode-compatible upscaler to pixel perfect HDMI.

mario

Compatibility

The current release of the board supports the PAL variants of the PPU, as well as most NTSC variants. NTSC support was developed and tested with the most common 2C02G. When the board detects NTSC, it assumes this PPU type and expects some very specific (buggy) behaviour. In case of other NTSC variants, where this behaviour is different (not buggy anymore), some visual glitches may appear. I expect this to happen for example in the game Bubble Bobble when more than 4 objects (players, enemies, bubbles) are on the same horizontal line.

Mod kit contents

The mod kit contains the FPGA board and a length of two-write cable to solder it to the RF output jack.

kit

Installation

Preparation

You need to disassemble the NES to get to the mainboard. Locate the PPU and see where it has the notch so you can install the PPUdigitizer in correct orientation. The PPUdigitizer will go to the underside of the mainboard to avoid the need to desolder the original PPU. This will probably even work when you already have a NESRGB installed on the topside.

Put some tape for electric insulation at the target location.

tape

Placement

Put the holes at the sides of the PPUdigitizer over the corresponding solder points of the PPU. Take care of the orientation. The two extra pads labeled GND and LUM need to be at the opposite end of the notch on the PPU.

placement

Soldering

Fill the holes with as much solder needed to make good contact. You don't need to solder all the pins. In the first board revision, those pins are marked with white rectangles. Later revisions (the ones with a larger central chip) show all pins with rectangles that do need to be soldered. If you are unsure, just solder all 40 pins.

Attach the two wires of the cable to the GND and LUM pads.

mounted

Repurpose the RF connector

As the RF modulator is largely obsolete by now, you can re-purpose its output jack for the Lumacode signal. To do that cut the PCB traces around the contact for the inner connector. Cut your wires to the minimum size required to reach this position. Then solder the one wire coming from the LUM pad to the point for the inner connector and solder the other wire to some nearby GND point.

rfmodulator

Alternative way of install

If you prefer a solution where the PPUdigitzer can be removed again more easily, you can watch
Adrian Black's video on this topic. But here the installation process is more difficult as it requires desoldering the PPU first.

Details on color encoding

For every pixel of the NES, the Lumacode signal contains 3 samples. With 4 luma levels per sample this gives 64 possible combinations that repesent an index in the NES palette.

A lesser known feature of the NES are the 3 color emphasis bits by which the programmer can additionally modify these colors by boosting either of the R,G,B channels. This emphasis bits are normally used to affect the whole screen so it is not necessary to transfer it on a per-pixel basis. Conveniently, several of the 64 colors indizes only show a black color, so these values can be used to modify the emphasis bits. The modified bits will be in effect until further modification.

This is the full encoding scheme. All colors signified as "black" are always black, regardles of the emphasis bits.

sample 1 sample 2 sample 3 raw index NES color emphasis
0 0 0 0 black off
0 0 1 1 black B
0 0 2 2 black G
0 0 3 3 black GB
0 1 0 4 black R
0 1 1 5 black R B
0 1 2 6 black RG
0 1 3 7 black RGB
0 2 0 8 $00 unchanged
0 2 1 9 $01 unchanged
0 2 2 10 $02 unchanged
0 2 3 11 $03 unchanged
0 3 0 12 $04 unchanged
0 3 1 13 $05 unchanged
0 3 2 14 $06 unchanged
0 3 3 15 $07 unchanged
1 0 0 16 $08 unchanged
1 0 1 17 $09 unchanged
1 0 2 18 $0A unchanged
1 0 3 19 $0B unchanged
1 1 0 20 $0C unchanged
1 1 1 21 black unchanged
1 1 2 22 $10 unchanged
1 1 3 23 $11 unchanged
1 2 0 24 $12 unchanged
1 2 1 25 $13 unchanged
1 2 2 26 $14 unchanged
1 2 3 27 $15 unchanged
1 3 0 28 $16 unchanged
1 3 1 29 $17 unchanged
1 3 2 30 $18 unchanged
1 3 3 31 $19 unchanged
2 0 0 32 $1A unchanged
2 0 1 33 $1B unchanged
2 0 2 34 $1C unchanged
2 0 3 35 black unchanged
2 1 0 36 $20 unchanged
2 1 1 37 $21 unchanged
2 1 2 38 $22 unchanged
2 1 3 39 $23 unchanged
2 2 0 40 $24 unchanged
2 2 1 41 $25 unchanged
2 2 2 42 $26 unchanged
2 2 3 43 $27 unchanged
2 3 0 44 $28 unchanged
2 3 1 45 $29 unchanged
2 3 2 46 $2A unchanged
2 3 3 47 $2B unchanged
3 0 0 48 $2C unchanged
3 0 1 49 $2D unchanged
3 0 2 50 $30 unchanged
3 0 3 51 $31 unchanged
3 1 0 52 $32 unchanged
3 1 1 53 $33 unchanged
3 1 2 54 $34 unchanged
3 1 3 55 $35 unchanged
3 2 0 56 $36 unchanged
3 2 1 57 $37 unchanged
3 2 2 58 $38 unchanged
3 2 3 59 $39 unchanged
3 3 0 60 $3A unchanged
3 3 1 61 $3B unchanged
3 3 2 62 $3C unchanged
3 3 3 63 $3D unchanged

RGBtoHDMI firmware

For the moment, the support of the RGBtoHDMI for decoding this signal is in a beta stage. The firmware can be found at https://github.com/IanSB/RGBtoHDMI/releases .