Sunday, March 5, 2017

Raspberry Pi 240p Composite Output

Big news for emulation on Raspberry Pis of any generation: a new firmware update has enabled 240p output through the composite video-out port (a dedicated port on older models and a combo 3.5 mm jack on newer models).

From Raspbian and its derivatives, you can run from a terminal:
sudo rpi-update
and it will automatically install the new firmware. For Lakka, the updated firmware will make its way into the main release at some point, but in the meantime, you'll need to mount your SD/microSD card on another machine and then find the 'boot' directory (for Lakka, this will be located in the ~500 MB partition that holds the system files rather than the bigger partition that holds your games) and make a backup in case anything goes wrong (not likely, but better safe than sorry).

Next, you'll need to download the new firmware files from github (here's a direct link to a zipped download) and copy them into the boot directory, overwriting what's already there. I believe you only really need a subset of the files (bootcode.bin, fixup.dat, fixup_cd.dat, fixup_db.dat, fixup_x.dat, start.elf, start_cd.elf, start_db.elf and start_x.elf), so if it acts strangely, maybe try cutting down to just those files.

In your config.txt, you can use the sdtv_mode directive to change to the new modes (either NTSC or PAL):
sdtv_mode=16    # progressive NTSC
sdtv_mode=0x10  # progressive NTSC (using hex notation)
sdtv_mode=18    # progressive PAL
sdtv_mode=0x12  # progressive PAL (using hex notation)
Also, make sure your config.txt isn't forcing HDMI output via hdmi_force_hotplug=1 (comment it out, if so) and you might want to force composite output, just to be sure, by adding hdmi_ignore_hotplug=1.

Raspbian and derivatives can now also change modes at runtime using the tvservice program:
$ tvservice -c "NTSC 4:3" ; fbset -depth 8 ; fbset -depth 32; tvservice -s 
Powering on SDTV with explicit settings (mode:0 aspect1)state 0x40001 [NTSC 4:3], 720x480 @ 60.00Hz, interlaced
for interlaced mode or:
$ tvservice -c "NTSC 4:3 P" ; fbset -depth 8 ; fbset -depth 32; tvservice -s 
Powering on SDTV with explicit settings (mode: 16 aspect:1)state 0x40001 [NTSC 4:3], 720x480 $ 60.00Hz, progressive
for 240-line non-interlaced mode.

Now, you'll notice that the above line still says 720x480 and applications will still see a 480-line resolution (that is, emulators will want to run at 2x scale). That's because the firmware still acts like normal 720x480 (or 576 lines for PAL) and the composite encoder just displays only half the lines.

This is actually to our benefit because it allows us to easily go back and forth at runtime and has the potential for on-the-fly switching (though RetroArch/Lakka doesn't support that and probably never will). It also allows emulators to show interlaced content without freaking out (that is, a "true" 240p resolution would cut off half of the picture, while this setup will just blank out every other line, which is much less obtrusive).

I have some pics here but, hilariously, the one from the new firmware turned out the worst:
RPi 240p Composite

Analogue Nt - RGB-PPU YPbPr

RPi 480i Composite
If you look closely, you can see that the RPi 240p shot has gaps between each scanline (easier to see on the green waves of the hill than on Luigi), while the 480i shot does not. What the still image can't show is that the 240p image is rock-solid stable, while the 480i image flickers sickeningly. Either way, the RPi composite output obviously does proper NTSC encoding, so blending of dithering and so on happens automatically without needing a shader, which is nice. EDIT: the NTSC encoding is (obviously, in retrospect) using the RPi's full 720 horizontal res timing rather than a console's native timing, so effects that depend on NTSC artifacting may or may not look like you would expect. For example, here's what the "tvpassfail" NTSC test ROM *should* look like:
NTSC Pass/Fail test ROM with maister's NTSC 256 px shader
But this is what the RPi's composite output actually shows:
NTSC Pass/Fail test ROM via RPi composite output
There's still crosstalk, of course, but it's spread across more pixels, which breaks the test. Perhaps unsurprisingly, it looks closer to the 320 px NTSC shader output:
NTSC Pass/Fail test ROM with maister's 320 px shader
With this new firmware, the RPi3 is now arguably the best/easiest/cheapest way to do proper 240p emulation on a typical NTSC standard-def television. Previously, a softmodded Wii was the undisputed champ in this area, as it was the only way to do 240p without putting a series of adapters and converters in the mix. The Wii still has an advantage insofar as it can output a high-quality YPbPr signal (i.e., comparable to the Analogue Nt shot above) but the RPi3 has the ability to emulate more consoles, including great Playstation 1 emulation via PCSX-ReARMed and decent N64 emulation via the core formerly known as GLupeN64 (now renamed to just Mupen64Plus-libretro). The Pi2SCART add-on from ArcadeForge can get a cleaner, "pixel perfect" output from emulators on the RPi, but at ~$50, it costs significantly more than the RPi itself, costs as much as a used Wii and requires adapters to work with standard NTSC televisions. So, in my opinion, RPi is the way to go for cheap/easy "240p" emulation on a regular ol' U.S. TV, while the Wii is a step up in visual quality but more of a hassle (and fewer games/consoles available to emulate). Pi2SCART wins in both respects but also adds significant cost.


Anonymous said...

Yeah, it's nice to finally have composite...

BTW, have you heard about the Analogue Nt mini "jailbreak"?:

It looks like it's great news for the FPGA scene.

Hunter K. said...

Oh yeah, that stuff's a pretty big deal. I probably would have bought one already if I didn't know the Zimba 3000 is on the way (someday). :)

Anonymous said...

Unfortunately, we don't know when the Z3K will be actually released, and the Nt mini is already out with its amazing features. I guess one can always sell the Nt mini to get some money back too.

Rpi3User said...

Look pretty nice. I already use the Wii for 240p and love it... but I would also like to emulate PSX, N64 and some games from NeoGeo which are pretty big for the Wii's memory so I'm very interested on this new feature on the RPi3.

However I have a question that's keeps me from trying it on my RPi3... it generates 240p, right? however not all consoles/games output exactly 240p, SNES output 224 lines as I recall and some other systems like MasterSystem 192 lines, or the GBA 160 lines... I was able to easily setup a proper resolution on Wii to change the displayed lines... How I can achieve this on the RPi? The only way I can think of is using a custom viewport but that will actually leave some blank lines at the top and the bottom of the screen, correct? Otherwise the image will be stretched and will not look good...

Any ideas how to overcome this?

Hunter K. said...

It shouldn't matter. The extra lines fall into the overscan area anyway, just as they would on a real console. It can take some fiddling to get it looking right (I know this, not from using the composite-out, which I haven't done much of, but on my arcade monitor using the HDMI-out), but most cores look just fine with integer scaling and overscan cropped.

Unknown said...

So far from my experimentations with Lakka and the new firmware there is no way to enable/increase overscan, so the image will always be too small. You need X11 to use xrandr to set overscan so the image (using integer scale, of course) will match native hardware (a real NES, etc.).

Hunter K. said...

You're right. I just tested it some earlier this evening.

I'm working on a PR to Picodrive to add a core option that adds in the extra 8 lines top and bottom. It should make it into the Lakka nightlies soon, once it's merged.

Kevin Fishburne said...

Hi Hunter. Made the last post as "Unknown", sorry... I just tried it with a vanilla Lakka and the new firmware with integer scale which gave me more overscan than I was getting before with my fiddled-with settings. I'm thinking we need a way to control overscan width and height independently, as for example the NES's 256x224 isn't a 4:3 AR. One way or the other this will get resolved, and I'm in the process of making a switch to flip between my RPi's Composite output and my actual NES's Composite output on the same TV so I can photograph and compare the two at high resolution with a mounted camera. I'm gunning for phosphor-precision accuracy to the real thing and will be able to test/verify it shortly. The Holy Grail is upon us. I can feel it. :)

Hunter K. said...

Oh nice. That should be helpful!

I pushed the overscan commit directly to the picodrive repo instead of sending a PR (whoops!) so it should be available in the next LibreElec nightly build. Hopefully, it will get the vertical scaling in proper shape.

Anonymous said...

> has the potential for on-the-fly switching (though RetroArch/Lakka doesn't support that and probably never will)

I wouldn't say never, because all that needs to happen is allow RA to change display mode when a core calls set_geometry or set_system_av_info, and to allow setting screen resolution based on the core's native resolution. The cores already provide the relevant information to RetroArch in most cases to be able to select a valid modeline (geometry.base_width, geometry.base_height, timing.fps), though there would need to be some way to have a valid range to avoid cases like handheld cores trying to set 144p display modes.

Unknown said...

FINALLY! Never say die eh?

But on another note, how does one activate TheMaister's NTSC filter on the Raspberry Pi?

Hunter K. said...

@Ted Michel
Heh, yeah, better late than never, for sure. :)

Unfortunately, I don't think RPis have the GPU grunt to run that shader. If you want to try it, there's a GLSL version that should work.

Unknown said...

I tried the glsl version, but Whenever I try to, my screen turns pink

Hunter K. said...

Ah, that means that the OpenGL version exposed by the hardware doesn't support float framebuffers :(

Unknown said...

So nothing can be done?

Scandy said...

On a RPi (Lakka) connected to a CRT TV via composite and sdtv_mode=16 (240p) which are the correct video settings (resolution, aspect ratio) to avoid scaling issues (vertical or horizontal lines during scrolling) with SNES games (Snes9x 2010)?
Is 240p really the right starting point to mimic the real snes video output on a CRT TV? This is driving me crazy ;)
Thank you

Hunter K. said...

@Alessio Scandy
It's not going to look perfect using the composite output, since the resolution it presents to the OS is hardcoded to something like 720x480 and SNES output doesn't fit into that evenly. The way to avoid scaling artifacts is to use integer scaling in all cases. Use a Custom Aspect Ratio and then increase it by integer factors until you get best fit. That's going to either have biiiig black borders or some pixels cut off the left/right with S/NES, though. If your display has easily accessible width control, you can probably push *most* of the black border off but it'll obviously be inappropriate for anything with a different horizontal res.

If you want it to look more exact, your best bet is to get a retrotink analog output hat and use a super-res. Those are more expensive than the RPi itself, though, so it may not be worth it.

Scandy said...

Hello and thank you very much for your feedback.

Indeed I've got a VGA 666 (less expensive than RetroThink) that allows to perfectly recreate original NES/SNES video modes on CRT TV (RPi > VGA 666 > cable VGA - SCART > TV). For some time now I use it with AdvanceMAME for real time resolution switch also on RPi (results are stunning, here's a tutorial I wrote in Italian... maybe advmame source code could be useful to implement CRT Switchres in LAKKA on Pi in the future).

Nevertheless, for the sake of authenticity, I was searching for a good setup with the only composite out. Well, stealing a bit 'from various sources and after multiple tries I think I found a very good setup for composite out:

1 - In config.txt I set sdtv_mode=16 (240p)
2 - In Lakka, I set Fullscreen resolution to 720x480 (actual RPi video mode)
3 - Then I set a Custom aspect ratio of 640x448
4 - Both Integer scaling ad Crop overscan options are off

So I get a pixel-perfect image with smooth scrolling and no pillar boxing or tearing on Genesis (Genesis-Plus-GX), NES (FCEumm) and SNES (Snes9x 2010).

Don't ask me why since, as I wrote, it was the result of empirical tests (or, please could you explain it to me? ;) but seeing is believing!

Hunter K. said...

oh, interesting! I don't know why those settings would work, but I'll try to give them a shot sometime soon. Thanks for sharing them!

Analytics Tracking Footer