Thursday, October 22, 2015

Bash Scripts for Non-Repeating Random Playback

I have an HTPC with a huge amount of files to choose from, which can lead to analysis paralysis / the paradox of choice: when there's so much to choose from, I end up consuming the same handful of media over and over instead of consuming a proper variety. Many media players have "shuffle" functions that will pick a random item from a list but that only works for traditional media and doesn't help with, for example, emulated video games. So, I decided to play around with some bash scripting to see if I could come up with anything more universal.

The first thing I wanted to do was to create a playlist based on a recursive scan of a directory. For example, I have my TV shows separated by show and then subdivided by season/series, and I want all of these files included in a playlist, which I accomplished with this script:
#!/bin/bash
if [ -e playlist]
then
rm playlist
fi
for f in **/*
do
echo $f >> playlist
done
This script will check for any existing playlist and delete it if it finds one already, then it search recursively and adds any files (but not directories, importantly) from any subdirectories to the playlist. If I add more files (e.g., I get new episodes of a show), I can just run the playlist-maker script again and it will delete the old playlist and make a new one with the new files added.

So that's great. However, these files are all in order and I want them to be randomly sorted instead (in case my desired launch program doesn't have a built-in shuffle function), which I can do like this:
#!/bin/bash
if [ -e random-playlist ]
then
rm random-playlist
fi
for f in **/*
do
echo $f >> nonrandom-playlist
shuf --output=random-playlist nonrandom-playlist
done
rm nonrandom-playlist
This script does all of the same steps as before but it also uses the shuf command, which is a common UNIX utility that will randomize the entries in the non-randomized playlist and then output a randomized playlist. The script then deletes the non-randomized playlist.

Alright. Looking good. If my playback program has a built-in shuffle function, I can just pass this playlist to it and it will shuffle among those files. However, as anyone who uses shuffle frequently will tell you, it often feels like a small minority of songs/videos gets played more often than others (whether this is actually true or not is up for some debate but it can be annoying all the same), so I want to remove entries from the playlist once I've consumed them so there can't be any repeats until every file has been played at least once:
#!/bin/bash
line=$(head -1 random-playlist)
echo "Next up: $line"
mpv --fs "$line"
echo "I have a lot of great memories from that episode..."
sed -i -e "1d" random-playlist
echo "And now they're gone!"
This script uses the UNIX utility head, which lists any number of lines from a file, starting with the first line. In this case, I just ask for the first line, echo it (for diagnostic purposes, and it will be useful later) and then pass it to my player (in this case, mpv). After playback is finished, it echoes again and then uses the UNIX utility sed, which is a super-powerful text/stream editor, to delete the first line ("1d") from the random playlist. It echoes one more time to complete the Bender quote and let me know that the entry was successfully deleted.

Ok, this is great but I don't want to have to always run my script to consume the next file. That is, I want to just get things rolling and have a marathon of random selections without continued interaction from me. To do this, we just wrap the whole thing in a 'for' loop, like this:
#!/bin/bash
for i in {1..100}; do
line=$(head -1 random-playlist)
echo "Next up: $line"
mpv --fs "$line"
echo "I have a lot of great memories from that episode..."
sed -i -e "1d" random-playlist
echo "And now they're gone!"
done
This will go through playing and deleting 100 times (you could make this 1,000 or 62 or whatever), which is great. However, I don't usually want to watch 100 episodes of a show, and if I launched this script from a desktop environment (i.e., by double-clicking), I have no way of stopping it! That is, each time I close my playback program, either because the episode is over or I clicked on the 'close' button, the next episode is queued up and starts automatically. If this were running in a terminal window, I could just close that window and it would stop the script in its tracks but this leads to a dilemma: it's not convenient to have to launch the script from a command line each time instead of double-clicking, and if I tell Nautilus (my file manager) to launch scripts in a terminal when I double-click them, it tries to run the scripts from my home directory instead of their actual location >.<

Thankfully, there's a solution. I can write a helper script that doesn't care if it runs from the home directory, and that script can launch my marathon script:
#!/bin/bash
DIR=$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )
x-terminal-emulator -e ./marathon-script
The first line of the script is a handy one-liner that navigates to the directory where the script lives. The second line tells it to launch whichever terminal application is registered to your alternatives system as the 'terminal emulator,' in my case it's gnome-terminal, and the -e switch tells it to run the marathon script inside that terminal, where we can easily view our diagnostic echo messages and close it when we're done consuming media.

As I mentioned, these scripts are easily modified to suit any kind of file, so I have some set up to launch a random NES game from my collection via RetroArch. I plan to use this setup to play through the entire NES library over a period of a few weeks/months.

Monday, September 7, 2015

SNES to NES Controller Adapter

Historically, the SNES was originally intended to be backward compatible with the NES, with a CPU from the same 6502 lineage as the NES and a similar controller signal protocol over the same 5 wires: data clock, data latch, serial data, +5v and ground. The SNES signal has more data clock pulses after the data latch pulse but the protocols are the same, otherwise. This means that if you make a pin-to-pin adapter that sends SNES controller signals to an NES port, everything works just fine and the NES will just ignore the extraneous clock pulses.

Now, original NES controllers are getting fairly expensive these days--particularly the "dog bone" controllers that are round instead of pointy--and the third party reproductions from Tomee et al. are pretty universally reviled for being flimsy, unresponsive and altogether crummy. SNES controllers, on the other hand, are more ergonomic, originals are generally more plentiful and some of the repros (like this one) are actually pretty great. I also already have a bunch of SNES controllers, including an ASCII Pad, which is possibly the finest third party controller ever produced...

So, with all of that in mind, I cobbled together an SNES to NES controller adapter (there are a number of guides online, see also: here and here, among others) using a couple of cheap extension cables, specifically Tomee NES extensions (I found a set of 2 from an eBay seller for $9) and "Gen" 2-pack SNES extensions. I'll post which wires I connected, but it seems the factories that produce these extension cables just pick a handful of randomly colored wires when they put them together, so don't assume they'll apply to your own cables in any logical way:
NES side   |   SNES side 
  Yellow  <->  Black 
  Orange  <->  Green 
   Black  <->  Red 
    Blue  <->  Yellow 
   Green  <->  White
Ideally, you would figure out which wire carries which signal using a multimeter but mine is on the fritz, so I just trial-and-errored my way through it, which was a pain in the ass, but whatever. It worked in the end. Interestingly and unexpectedly, NES' B-button becomes the SNES' Y-button, and NES A becomes SNES B, which is really fantastic, since the angle of the SNES B and A buttons would make them hard to press at the same time had the naming/mapping been consistent.

Thursday, August 27, 2015

Analogue Nt HDMI - First Look

I finally got my Analogue Nt with HDMI upgrade in the mail today and while the base Nt has already gotten plenty of coverage, the HDMI-upgraded model hasn't been covered at all (AFAIK) at the time of this writing.

I got the default silver model with the "limited edition" white and gold controller ports:
As covered elsewhere, the construction is incredibly high quality (the power/reset button being a button from an NES controller is a particularly interesting touch, I thought):
There has been much ado about the aluminum cart slots scratching up cart shells, which hasn't been a problem for me, but I suppose if you're really worried about it, you could open the flaps with a finger while inserting the cart. /shrug

Below the HDMI port is a standard 15-pin d-sub connector, which I've seen called a "VGA port" elsewhere, though this is not the case. That is to say: you can't hook it up to a VGA-compatible display and get any video out of it. For that matter, it's apparently not RGBHV-over-d-sub, either, as it didn't produce any picture when hooked up to my multisync XM29+'s d-sub port, even though that monitor will accept "240p" non-interlaced video over that connection. I'll have to catch up with the guys at Analogue and ask about the pinout of the port. Hopefully, it's something that won't require too much effort to get going on my own. I'm planning to hack together a SCART cable and a working RGBHV-over-d-sub cable (if possible). EDIT: I just talked to the Analogue guys and it seems the HDMI and RGB/component functionalities are mutually exclusive. It seems they will swap between the two at no charge, though:
"When you upgrade your Analogue Nt to HDMI it outputs HDMI only, there are two different systems that are not compatible with each other. Though, whats cool is you can switch between RGB and HDMI if you wanted either version (we'd install either daughterboard for you for free). Also, any other cool mods that the NES community may make in the future would be compatible with the Nt too - which is super cool!"
That in mind, I may decide to switch to RGB at some point in the future, as much of my equipment is tooled for RGB/SCART/JP21, but for now HDMI is convenient.

I won't rehash any more of the information that's readily available elsewhere, so instead I'll spend most of this post talking about the HDMI upgrade. While originally advertised as an external upscaler, they eventually nixed that idea (and rightfully so, since it's not likely they'd be able to get anything worthwhile for the ~$60 cost of the upgrade) and opted instead for kevtris' brand new HDMI board, which AFAIK isn't available anywhere else just yet.

I'm still doing testing to get a feel for what the HDMI board is capable of, but out of the gate: it's pretty incredible. The image is exactly what you would expect from an emulator, warts and all. That is, the upscaled pixels are as sharp as you can get; much sharper than the output of an XRGB-Mini Framemeister (which I also have, so I can give them the Pepsi Challenge):
The colors in those shots are washed out, but that's the fault of my camera trying to adjust to the brightness of my TV's backlight. The colors are actually bright and vibrant, and the HDMI connection has none of the "shimmering" on large swaths of color that have been reported elsewhere with RGB connections.

Getting into the HDMI onscreen menu is pretty cool/crazy in that it's a button combination on the gamepad (specifically, dpad-down+select by default). Once there, it's got a ton of cool options for tweaking the video, including overscan cropping, horizontal scaling, scanline settings, scaling filters and resolution selection driven by your display's EDID:
At 1080p, the scanlines are uneven thickness (alternating thinner and thicker), just like you would get on an emulator at 4.5x scale:
1080p's uneven scanlines
I would have liked to see an option to force integer scaling to avoid this issue, but I didn't see anything like that (I'll update this post if I find otherwise; such a thing may also be added in a future firmware update UPDATE: 9/26/2015 looks like kevtris is on it). At 720p, the scanlines are even thickness, since it's an even 3x integer scale already, but the pixels aren't as sharp due to my TV doing the rest of the scaling:
720p's even scanlines
Scanline settings. NES is locked to the resolution, while the others are pre-set scale factors (i.e., they don't always line up with the pixels, which I can't stand). There's also an intensity slider that controls how dark the lines are.
Likewise, at 1080p, the vertical size of pixels isn't consistent, just as you would expect from nearest neighbor scaling at a non-integer scale factor. This is also the case with the horizontal scaling, but there is an option screen specifically for tweaking it, from 3x (for 1:1 PAR at 720p) up to stretched 16:9 (barf). The default setting is 4:3 on 16:9 displays, which has faintly warped pixels but is the natural aspect ratio for NTSC:
1:1 PAR (i.e., square pixels) using 3x horizontal scale at 720p; notice the even checkerboard pattern in the road.
4:3 aspect ratio; notice the uneven pattern on the road.
There's also a preset for 4:3 on 16:10 displays, which is handy if you're hooking up to a monitor instead of a TV, as well as an option labeled "interpolation," but I can't really see any difference between it being enabled/disabled.

There are also scaling filters, including the ever-popular hq2x/hq3x/hq4x (no filtering vs hq4x):
No scaling filter
HQ4x scaling filter
The HDMI board also includes a lot of audio settings, with individual enable/disable toggles and volume/panning for main audio and each specific add-on audio chip for FDS audio and any in-cart audio add-ons, like the ones in Gimmick and Akumajou Densetsu:
Independent volume control for each audio device
There are a ton of other options I haven't gotten to play with yet, including hotkeys for over/under-clocking (presumably to get around some incompatibility with the Everdrive N8, which I haven't gotten to test yet), soft-reset and more.

UPDATE (8/30/2015): Looking into the Everdrive issue, it seems the N8 is indeed incompatible with kevtris' HDMI board with N8 firmware >= 4.0, while the 3.0 firmware may be okay. The Analogue folks uploaded a copy of the older firmware to their Dropbox account. Testing is easy, just copy and paste the files onto your SD card and replace the newer versions. Leave me a comment if you get to try it. I hope to borrow a friend's N8 soon, so hopefully I can provide some input/testing.

Update (9/25/2015): KRIKzz got his hands on an HDMI board and has been investigating the issue. Hopefully, a fix will be forthcoming. Update (9/28/2015): Oh sweet: looks like he's got it working! Anyone with the HDMI board should upgrade their N8s to firmware v13. Update (10/3/2015): d'oh, not working for me :(. I get a garbled mess if I boot my new N8 with no SD card and a green screen with firmware v13.

In addition to the N8 issues, Kevtris' HDMI board has been having issues with some games and mappers, the most popular of which is Castlevania 3. Apparently, holding reset while powering on the console alleviates some of the issues but this isn't an option on the Nt. Kevtris is working on it, though, and it should be addressed in the upcoming update. Update (10/30/2015): Kevtris' update is out and it apparently fixes the Everdrive green screen, FDS and MMC5. Anyone still having the Everdrive green screen issue can still apply the update from their Everdrive by powering on with the HDMI cable unplugged, wait a few seconds for everything to initialize and then plug the HDMI cable back in.

I plan to update this post as I learn more but I wanted to get this info out there, both for people waiting on their Nts and for those eager to learn more about kevtris' awesome HDMI board (for reference, it seems my board's serial number is 30, so I would assume it's one of the first to make it into an end-user's hands).

Anyway, here are a couple more glamour-shots:

Saturday, August 22, 2015

Retr0brite Is Just Hydrogen Peroxide Plus Filler

I bought an SNES Mini on eBay the other day with the intention of applying an RGB restoration mod + csync. It was in decent condition other than a few scuffs and some extensive yellowing of the plastic, which I decided to try correcting with some "Retr0brite."

After reading up on recipes and some related forum posts, I decided not to go through the trouble/expense of buying and mixing up actual Retr0brite paste, which contains glycerin and xanthan gum, and instead focused on the active ingredient: concentrated hydrogen peroxide. Recipes typically call for some low-concentration, aqueous hydrogen peroxide, like you find in the big brown bottles, bolstered with OxyClean--basically dehydrated hydrogen peroxide powder--and thickeners to make a paste that you can spread onto things. This in mind, it doesn't make much sense to use relatively expensive low-concentration hydrogen peroxide as a base when you could just start with regular water and add more OxyClean...

If you have access to a Sally Beauty Supply store, they sell bottles of 40 vol creme developer, which has an even higher concentration of hydrogen peroxide than OxyClean and is already goopy, so you don't need to fool with the glycerin/xanthan gum to get it to stick to stuff. This can be helpful if you don't have an appropriately sized container in which to submerge your plastic, and reports suggest that it works within hours rather than days. However, you need to be more cautious with this, as it can damage clothing and skin/hair.

Anyway, I skipped the low-concentration stuff and just dumped a bunch of OxyClean into a roasting pan full of water, plopped the top section of my SNES Mini in and left the whole thing out in the sun for 2 days (you'll have to replenish the OxyClean periodically, as it seems to lose its mojo over time).

The first day, I didn't put nearly enough OxyClean in, so there was very little improvement. The second day, I drastically increased the concentration and had much better results. I found that, in a properly high concentration, the plastic should be more buoyant than the solution, so you'll need to hold it down with something. Also, there seems to be some disagreement as to whether the process needs actual sunlight or if any light source will do. In my case, there was no effect from 8 hrs under a CFL light bulb, so the sunlight (or a UV lamp) seems to be necessary.
Before
After
It's not perfect, but it's a pretty dramatic improvement, I think. The RGB+csync mod was a success, as well! The resulting picture is noticeably sharper than on my older model (the model with the sticker underneath the power button) and there's no annoying bright vertical line going through the center of the screen. The colors are identical to the original model because I put 1.1k ohm resistors on each line to dim the channels. The tutorial I linked above mentions this as an optional step and I highly recommend it.

Saturday, August 1, 2015

NEC XM29 Plus Broadcast Monitor

I lucked into another broadcast monitor recently, this time the "holy grail" of retro gaming monitors, NEC's XM29 Plus. I won't rehash a whole bunch of info that's available elsewhere, but I will provide some answers to questions I had as I started using it:

Unlike the Sony PVM series, the XM29 Plus has no support for component inputs, but it supports almost everything else (Svideo, composite, RGBHV, VGA). You can get a YPbPr-to-VGA transcoder, like this thing, but most of them (including that one) don't support resolutions below 640x480, so they're not good for PS1 (which frequently jumps between 480i and "240p"), non-progressive PS2 games (admittedly, the vast majority of PS2 games are 480p-capable), or "240p"/doublestrike emulation via Wii homebrew, etc.

That said, I don't think component is a particularly useful on the XM29, which is a shame because that's what I had settled on for use with my PVM. Instead, it seems best to stick with RGB SCART, which is easily converted to RGBHV, as the XM29 has two of those inputs available. You will need a sync cleaner, though, so either get a sync strike or get a cable with a sync cleaner built-in, like this one.

There's a lot of uncertainty online about which resolutions work over SCART but I can answer definitively: 480p over RGB SCART totally works fine.

Other than that, there's not much else to say. Low-res non-interlaced content has extremely sharp scanlines with thick, black spaces between them, which some people don't care for. Likewise, interlaced content bobs very visibly when sitting close to the screen. Slight geometry issues are also apparently common on these monitors, and mine's no exception. However, it still looks great and many of the imperfections can be hidden with a teensy bit of overscan.

Here are some shots (click to embiggen):
240 noninterlaced full frame TATE
240 noninterlaced closeup TATE
480i
480p

Thursday, June 25, 2015

Latency Testing

My student worker, Alex, borrowed a digital oscilloscope and photoresistor from a coworker of mine and we sat down at my workstation to collect some data in an area that's often discussed (vociferously!) but rarely actually tested: latency. Most latency testing is unscientific voodoo ("I can *feel* it") that also suffers from confused terminology (see: the fighting game community's complaints about "lag" and how it makes them drop their combos). In this case, we're specifically examining input latency; that is, the difference in time between pressing a button on the controller and the action taking effect on the screen.

Here's a picture of our test bench, which consisted of a button from my trusty Happ-modded Mad Catz SE wired into the aforementioned oscilloscope:
The input from the button is compared against the voltage running through the photoresistor attached to a battery (and a momentary switch to keep the resistor from just draining the battery):
The photoresistor gets placed against my computer monitor while the button is used to make things happen in the emulators. As the brightness changes underneath the photoresistor, the resistance also changes changes, and the oscilloscope displays the difference in time between the voltage drop in the button and the change in voltage from the resistor/battery circuit, which looks something like this:
We only had the equipment for a day, so I couldn't test as much as I would have liked, but I tried to be as consistent as possible. To that end, we sampled 5 data points for each variable and did all of the testing on the same machine. All SNES comparisons used the Super Famicom Controller Test  ROM, while the arcade comparisons used Espgaluda from Cave (in hindsight, probably not the best choice, but it's what I had on-hand). I also didn't have a good way of getting a baseline latency--I'm using a modern, crappy Dell LCD setup rather than a CRT and Windows 7 64-bit, which I chose out of both convenience and the assumption that it would be similar to a typical user's setup--so I was forced to provide data for *total system latency* rather than being able to isolate the latency caused by the individual variables. In attempting to get some sort of baseline, we held up the tester to the built-in gamepad testing applet in Windows, which gave results hovering around 75 ms, which is obviously not accurate, since some of our emulators performed better than that... With that in mind, these results should only be considered relative and not absolute.

Note: my full system info is Intel i7 Sandy Bridge with AMD R7 200 series with all of the GPU control panel crap turned off except for Eyefinity.

Anyway, here are the graphs that illustrate some of the more interesting comparisons:
First off, Aero compositing is bad news for both latency and variance. The increased variance is a real kick in the pants because it makes your performance less predictable. If you want consistent behavior and generally improved latency, stick with a "classic" non-Aero theme. Interestingly, disabling Aero did not seem to help with Higan.
Overall, this graph shows us that exclusive fullscreen is significantly better than windowed for latency, which is expected based on our Aero compositing findings. You'll notice there's no benefit to fullscreen in Higan (it's worse, in fact) because it's not *exclusive* fullscreen. Instead, it's what's known as "windowed" or "borderless" fullscreen. You can also see that ZSNES in exclusive fullscreen is extremely fast; faster than my supposed baseline of 75 ms :O
Higan had the highest latency figures here, even after correcting for the shaders--which I'll talk about more in a sec--with RetroArch about a frame lower (this includes data from both the snes9x and bsnes-compatible cores, which were not significantly different [87 ms vs 92 ms, which is within the variance of USB polling rates]). This also combines both windowed and fullscreen, which hurt ZSNES and ZMZ, the clear winners in exclusive fullscreen mode from our previous graph. Note: when ZSNES and ZMZ went into exclusive fullscreen, they broke Eyefinity, which other testing suggested adds up to ~8ms (or a half-frame) of latency, so keep that in mind when looking at their results.
This one was a dagger in my heart, but I'm posting it here anyway because of SCIENCE. I had always assumed that shaders would never increase latency because, in a worst-case scenario, they would just reduce the framerate (i.e., if the shader takes >16 ms to render). This is obviously not the case, as cgwg's crt-geom increases latency considerably in both Higan and RetroArch, as does crt-lottes. Crt-hyllian, on the other hand, has almost no effect on latency. To explore whether it's just heavy-duty math that causes the latency and whether it's exacerbated by multiple shader passes, I also tested Hyllian's xBR-lvl4-multipass in RetroArch. Shockingly, this one produced lower latency than no shader at all, which I find highly dubious.
I kept this one in here because there's been a contentious debate as to which of these platforms provides the best experience for emulating arcade games. However, there are some serious caveats to keep in mind before drawing too strong of a conclusion: 1.) this used a different test ROM from the SNES emus, 2.) the test ROM I used was selected out of convenience and actually had a lot of potentially confounding noise in the form of enemy bullets passing through my test area, 3.) GroovyMAME and RetroArch are really at their best running in KMS via Linux rather than Win64, so they would likely have more pronounced benefits vs mainline MAME if I could have measured that, and 4.) in initial testing the day before I ran these measurements, mainline MAME performed incredibly badly, with GroovyMAME close behind, which suggests that there may be some other variance involved.

That all said, these data indicate that RetroArch is approximately 1.5 frames slower than GroovyMAME, while the difference between mainline MAME and GroovyMAME is within the variance of USB polling rates. However, in light of the counfounders, I think the strongest conclusion we can draw reliably from the arcade comparison is that RetroArch isn't any *better* in Win64 (i.e., a null finding), so users should go with whichever platform has the features that best suit their needs rather than worrying about slim-to-nonexistent latency differences.

Conclusions

While the testing was not 100% reliable due to multiple confounders in several areas, we can see some trends emerge that can inform our discussions about latency in emulation. Windowed is definitely worse than fullscreen, and enabling Aero compositing is worse than without while also increasing variance and unpredictability. Shaders can actually cause excess latency, sometimes severely so. ZSNES, which has become a bit of a punching bag among SNES emulation scenesters, has outrageously low latency in fullscreen, so if you can stomach the terrible accuracy, there's actually some justification for using it now other than OMGSNOW!1! Alcaro's ZMZ also performed very well and can utilize more accurate emulation cores, so it can be a means to leverage some of ZSNES' latency benefits without being stuck with its poor accuracy.

In the future, I would like repeat these tests with a CRT monitor, which would have a predictable baseline of near 0 ms. I would also like to test latency in other environments, namely Linux+KMS. Finally, it would be very useful to have some comparative figures for original SNES hardware (both via CRT and upscaled via XRGB-Mini) and for RetroArch running via console.

Here is a link to download the raw data in Excel format, in case anyone would like to look at the numbers in more detail and/or perform other comparisons that I didn't think of.

EDIT: I think some people are drawing more conclusions from these data than is really appropriate; specifically, some folks are trying to draw direct comparison between the emulators/frontends tested. These data are simply not extensive enough for that. Furthermore, it's important to keep in mind that I didn't test the quality of sync, which could heavily affect the results. Namely, ZSNES and ZMZ both suffer from frequent audio crackling and frame stutters, which indicate issues with vsync, while RetroArch has none of either. I didn't test RA with vsync disabled (i.e., blocking on audio with video tearing), which could have an effect, and in general gameplay, users need to decide whether improvements in sync are worth minor (potential) increases in relative latency.

Tuesday, April 14, 2015

More CRT Shaders

There have been a number of new CRT shaders written since I last did a big roundup, and some people have asked about it, so here we go! All Cg-format shaders are available in libretro's common-shaders repo on github, while all Quark shaders are available in my github repo. All shots were taken at 4x scale factor, and the closeups are scaled up 400% with nearest-neighbor. Click the thumbnails to embiggen:

CRT-Geom

I've already written about this one at length, but I figured I'd include it here anyway for reference and comparison. It's the original awesome CRT shader written by cgwg with some help from Themaister and DOLLS[!], and it's still a good choice. It has extensive customization available via code modification and/or RetroArch's runtime shader parameters.
 Many users don't care for the curvature effect and turn it off, like this:
This shader is available in Cg and Quark formats.

CRT-Easymode

This one was written by a fellow from the NeoGAF forums who goes by the name Easymode. It is notable for looking nice even at non-integer scale factors and for being very lightweight considering how nice it looks. It's a good one to try on mobile platforms and desktops/laptops with weaker GPUs. It also has some nice runtime parameters for switching between cgwg-style and Lottes-style mask effects.
This shader is available in Cg format only.

CRT-Hyllian

This one is written by Hyllian, who is well-known for his popular upscaling interpolation algorithm known as xBR. It includes some interesting options, such as a "blue boost" that is helpful for making water in many games go from purple to blue.
This shader is available in Cg format only.

CRT-Lottes

This one was written by Timothy Lottes, an engineer at Nvidia who is known for his work creating the FXAA fullscreen antialiasing GPU algorithm. This shader is adapted from the shadertoy he made and was generous enough to release into the public domain. Notably, it uses a sideways shadow mask effect that is designed to avoid chromatic aberration.
 It's easy to flatten this one out, as well, using RetroArch's runtime parameters to set the warpX/warpY values to zero or by commenting line 142 in the Quark shader:
This shader is available in Cg and Quark formats.

PhosphorLUT

This is one I worked on awhile back and it only focuses on doing a phosphor/shadow mask using an external lookup texture (LUT) and a little bit of horizontal blurring.
You can adjust the scale of the phosphor mask with 1.0 looking more like a high-res CRT monitor, while 1.5 and 2.0 look more like an SDTV or CGA monitor. As you adjust the scale, the colors can get wonky, so there are runtime parameters for dialing in the right balance. Here it is at a scale of 1.5:
 There's also a preset for use with 4K displays (not pictured here). This shader is available in Cg and Quark formats.

GTU

I've raved about this shader--which was written by aliaspider--before for its ability to blur out dithering, but it also belongs on any list of good CRT shaders. While it doesn't provide any phosphor/shadow mask effects, it does allow horizontal/vertical bandwidth control (for blending things like pseudo transparency and dithering), scanline effects and NTSC color blending/bleeding.
All of these effects are user-customizeable by editing the code (he put the various options right at the tops of the files for easy access) and, with the NTSC color option disabled, it looks remarkably close to the output of Micomsoft's famed XRGB-Mini Framemeister deinterlacing/upscaling device.

This shader is available in Cg and Quark formats.

CRT-Royale

This shader was written by a guy named TroggleMonkey and it uses some intense, RetroArch-specific black magic to overcome many of the issues with CRT emulation that I thought were unavoidable, particularly using large-scale blurring passes without totally wrecking performance and making a true RGB phosphor / shadow mask that looks good at less than 4K resolution. As I said, it is Cg-only and only works on RetroArch, at that (i.e., no OpenEmu, even though it supports Cg in general).
CRT-Royale has an option (on by default and in these shots) for simulating the characteristic glow of a CRT tube. This is another common goal of CRT shaders, and I've broken those off into their own group:

Glow/Halation

Glow

Written by Themaister, this one eschews phosphor/shadow mask effects and just focuses on using special blurs to accentuate the variable beam width of a CRT (i.e., brighter pixels bleed further into the space between scanlines).
 He also made a variant that tacks on his NTSC-composite shader (looks better in motion):
This shader is available in Cg format only.

CRT-Hyllian-Glow

Just like regular CRT-Hyllian, but with some whole-screen blur/glow.
This shader is available in Cg format only.

CRT-Lottes-Halation

Mr. Lottes made a revision to his scanline shadertoy that added a number of gaussian blur kernels to bloom out bright pixels, which increases the overall brightness of the image without getting the fullscreen haze of some of the other options.
Unfortunately, the limitations of the shadertoy format forced the blurs into a single pass, which is extremely slow. This variant is available in Cg format only.

For anyone who's curious, I took 4K screenshots of most of these, but blogspot down-rezzes them and adds jpeg compression on top of that, so I couldn't post those directly. Instead, here is a download.