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.
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.
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.
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.
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.
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.
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 .