-
Notifications
You must be signed in to change notification settings - Fork 2
PPUdigitizer (for NES)
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.

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.
The mod kit contains the FPGA board and a length of two-write cable to solder it to the RF output jack.

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.

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.

Fill the holes with as much solder needed to make good contact. You don't need to solder the points that are inside the white rectangle markings (but it does not hurt if you do).
Attach the two wires of the cable to the GND and LUM pads.

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.

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 |
For the moment, the support of the RGBtoHDMI for decoding this signal is in an early alpha stage. You can download an experimental firmware right here: alpha_nes_support_2024-08-01.zip This software can not yet handle the (rarely used) color emphasize bits.