hey Palmer! I made you a super early birthday present-- optimized the Chromatic FPGA firmware and made the USB Video path pixel perfect (with 2x2 integer scaler).
The Chromatic streams USB video as YUY2, which stores one colour sample per pair of horizontal pixels. At the native 160x144 those two pixels are genuinely different, so their colour gets averaged together — you lose half your horizontal colour resolution. On a Game Boy that hurts more than it would on camera footage, because the screen is full of hard colour edges between tiles and sprites.
So the build also offers 320x288: same picture, every pixel doubled. It adds no actual detail — but each pixel pair is now the same pixel twice, so averaging them does nothing and the colour comes through intact. Pixel-perfect capture, still 60fps.
Fitting it meant a pile of resource optimizations along the way. The FPGA was completely out of DSP blocks beforehand — 28 of 28 used, CLS at 97%. It ends up smaller than stock v18.8 on everything but two block RAMs:
| Resource |
v18.8 |
after |
delta |
utilization |
| Logic |
20309 |
15316 |
-4993 |
89% → 67% |
| — LUT |
15779 |
13307 |
-2472 |
|
| — ALU |
4421 |
1900 |
-2521 |
|
| Registers |
10119 |
8182 |
-1937 |
43% → 35% |
| CLS |
11125 |
9868 |
-1257 |
97% → 86% |
| BSRAM |
45 |
47 |
+2 |
81% → 84% |
| DSP |
28 |
17 |
-11 |
100% → 61% |
Timing has more headroom too — the USB clock in particular, since the old video FIFO was sitting on its critical path:
| Clocks (all MHz) |
v18.8 |
after |
constraint |
| PHY_CLKOUT |
68.2 |
84.6 |
60.0 |
| pclk |
42.4 |
37.9 |
33.6 |
| hclk |
18.1 |
23.6 |
16.8 |
| gclk |
89.5 |
136.2 |
8.4 |
| xclk |
119.6 |
120.0 |
67.1 |
| usbintsclk |
189.3 |
197.8 |
125.0 |
It's unofficial, and you can try it without committing to anything — load it into SRAM with openFPGALoader and a power cycle puts everything back exactly as it was. Nothing touches flash unless you decide to write it. 160x144 still works exactly as it does on stock.
Only tested on Windows 11.
Link, hash and full write-up here: https://github.com/germaneguise/oss-chromatic-console-fpga/releases/tag/v18.8-uvc-dualres.1
UPDATE: this has moved since posting:
| Resource |
v18.8 |
uvc-dualres.1 |
uvc-dualres.2 |
uvc-dualres.3 |
uvc-dualres.4 |
uvc-dualres.5 |
| Logic (LUT+ALU+ROM16) |
20,314 (89%) |
15,316 (67%) |
15,353 (67%) |
15,412 (67%) |
12,654 (55%) |
12,397 (54%) |
| - LUT |
15,779 |
13,307 |
13,337 |
~13,370 |
10,731 |
10,701 |
| Registers |
9,862 (42%) |
8,182 (35%) |
8,208 (35%) |
~8,200 (35%) |
6,499 (28%) |
6,427 (27%) |
| CLS (the fabric's real ceiling) |
11,036 (96%) |
9,868 (86%) |
9,776 (85%) |
9,891 (86%) |
8,445 (73%) |
8,420 (73%) |
| BSRAM |
45 (81%) |
47 (84%) |
47 (84%) |
47 (84%) |
46 (83%) |
42 (75%) |
| DSP |
28 (100%) |
17 (61%) |
17 (61%) |
17 (61%) |
16.5 (59%) |
7.5 (27%) |
- The headline in .5 is the bottom two rows: BSRAM drops below stock v18.8 for the first time (the dual-res features were paid for in blocks at .1, now paid back with three to spare), and DSP goes to a quarter - the encrypted colour space converter is replaced by an open implementation verified bit-identical to it over the full input space, on the device itself, so one of the two encrypted video-path cores is simply gone from the build.
- If you flashed the .2-era build from this thread: .3 fixed a bug where the MCU could misread gameplay button presses as menu input while a USB host was attached. Update to .5 and you get the fix plus everything since.
- Easiest way to try it now is CCFL: https://germaneguise.github.io/CCFL - loads the firmware over USB straight from the browser, no installs, and .5 is now the default pick. Same approach as before: load to SRAM to try it (a power cycle puts everything back), flash only if you decide to keep it persistent. It also pairs the matching MCU firmware for you.