Friday, May 4, 2018

More New Shaders

This post is a companion piece to yesterday's post, which focused on shaders for low-power devices. This post doesn't have any particular focus but showcases a few recently added shaders.

As always, click the thumbnails to embiggen.

PAL-r57shell

The PAL video standard used throughout Europe typically doesn't get the attention from retro-gaming enthusiasts that NTSC--the standard used in both Japan and the U.S.--enjoys. That is, no games (that I know of) depend on PAL video artifacts for any effects, and as a result, few people have shown interest in reproducing the characteristics of the PAL standard.

One of those few, who goes by the handle r57shell, made a PAL shader a few years back that captured some of the effects, but they recently updated it to make it much more complete and comprehensive. This new version is more comparable to the NTSC simulations by blargg and Themaister in quality and accuracy, and it includes some nice NES-specific options, as well. For example, by uncommenting a line in the shader, it can be used to bypass traditional emulator palettes and generate its own from the raw color and emphasis data (in emulators that expose the 'raw' palette).

By default, it doesn't do that, though, so it can be compatible with non-NES cores:
r57shell also made a preset that puts his shader in front of CRT-Royale to get the full retro effect:

MMJ_Cel

This shader has been available for Pete's OpenGL 2.0 plugin for ages, but its author, MMJuno, recently ported it to RetroArch's shader format(s). The shader applies a cartoony black border on edges and changes smooth gradients to chunky steps. It doesn't look very good on simple 2D content, so I dropped my normal Super Mario World screenshot for this image from Super Mario 64 that can better illustrate the effect:

VHS

This is one I made that combines some shadertoy effects to mimic the look of a crappy VHS recording:
The OSD 'play' message blinks on and off for a few seconds after the game loads and then goes away. The GLSL version of the shader also supports a fun effect whereby using RetroArch's rewind function creates a static-y tracking effect and prints another OSD message while rewinding. Setting the rewind granularity to 2x or 3x really clinches the effect (looks better in motion, of course):

Technicolor

After playing Cuphead, I wanted to try and make something similar, so I used a lossy CMYK conversion paired with film grain, simulated misalignment of the different color layers and vignetting/hotspotting to try and mimic an old-timey projector setup:
It doesn't translate well to still pictures, but it also blips single frames of film noise (scratches and hairs) onscreen pseudo-randomly:

xBRZ-Freescale

I mentioned this already in the low-power shader post, but I feel like it's worth mentioning here, too, because it's kind of a big deal. It's not often you get to say "welp, don't need those shaders anymore," but that's exactly the case here. Due to its superior speed and sharpness at any scale, there's no real reason to use the other xBRZ shaders:
Of course, other xBR permutations, like the various 'super' versions and mlv4-multipass, etc. still have their own characteristics and reasons for use, so don't misunderstand this as obsoleting those, as well. It also doesn't have quite the search range of ScaleFx, so some of the shallow slopes that shader catches (like the one under the dragon coin) are only partially smoothed by this one.

simpletex_LCD

I mentioned this one in my last post, as well, since it's also quite fast, but I wanted to include it here because it's such a pleasant effect:
There are several permutations of this shader that combine that same nice paper texture and light (instead of the more typical dark) grid-lines with Game Boy Color or Game Boy Advance color simulation.

Thursday, May 3, 2018

Shaders for Low-Power Machines

This started out as one big post with a bunch of new and new-ish shaders, but I decided to bust it up and hopefully make this a little more useful and focused. Be sure to check out the next post for some more fun shaders.

While there's no shortage of heavy-weight, gorgeous shaders that will make even a modern gaming GPU howl, a lot of people use older machines, single-chip computers (such as Raspberry Pis) and machines with integrated graphics that simply don't have the grunt to take on those hefty shaders. It can be tedious digging through the hundreds of shaders available to try and find the few that might work on lower-powered GPUs, so I wanted to present a few of those here.

As always, click the thumbnails to to embiggen.

Lightweight CRT Shaders
CRT-Potato
bparker created these shaders with the goal of bringing some of the more popular CRT effects to even a "potato" of a computer. They work by tiling a tiny lookup-texture across the entire screen.
The 'cool' version has a bit of a blue tint to it, but this can be helpful in making purple stuff, like the sky in Super Mario Bros and the water in Secret of Mana, a little bluer:
The 'warm' version is patterned after the 'kurozumi' preset for CRT-Royale:
zfast-CRT
Written by SoltanGris42, this shader is intended to run full speed on and work around some of the GPU quirks of the SNES Mini/Classic and can also reach full speed on a RPi3 at resolutions of up to 1920x1080 or even 1600x1200:
fakelottes
CRT-Lottes is a great shader, but the bloom and scanline effects are a too much for many weaker machines, so I took the beautiful mask code and combined it with a basic scanline shader to produce something that's still reasonably handsome and should run full speed on a RPi3:
It's also worth noting that fakelottes' scanline code looks pretty decent even at non-integer scales.

CRT-Pi

I think I've covered this one--written by davej--before, but it's worth mentioning again because it looks great and is designed specifically around the constraints of the Raspberry Pi GPUs (RPi1, RPi2 and RPi-Zero need to be overclocked for 1080p/60):

LCD Grid
zfast-LCD
Another lightweight shader from SoltanGris42, this shader does nearest-neighbor scaling and then darkens the border pixels to mimic a low-res LCD pixel grid. The thickness and darkness of the grid are adjustable:
simpletex_LCD
From jdgleaver, this shader is mostly intended for use with non-backlit systems, like the original Game Boy, Game Boy Color and Game Boy Advance, but it looks cool with pretty much anything. It uses the line-weighting equation from zfast-LCD but adds a lot of nice options and a cool background texture effect:

Basic Scanlines
RiskyJumps and I had similar inspiration for these shaders: what is the essence of a scanline effect?

Scanlines-Sine-Abs
Requring just a bare handful of GPU cycles to process, this shader just draws a vertical sine wave across the screen, which makes for a pleasant, rounded scanline effect that looks pretty decent even at non-integer scales:
 Scanline-fract
In contrast, my scanline-fract shader looks just awful at non-integer scales. However, it scales up nicely to any integer and draws even black lines (or as dark as you please) across the screen with any thickness (in pixels) you choose. The default thickness is a half-pixel, but you can make them thinner or thicker:

Smoothing/Interpolation
xBRZ-Freescale-Multipass
I don't know if this shader will run on an RPi3 or not, but it's certainly very fast. By leaving out the pixel rasterization step, aliaspider was able to get sharp edges at any scale and without the computation burden of that process. On my crummy office workstation GPU (a Radeon 200-series), it gets well over 1,000 frames per second. Even so, it looks great and has the fantastic edge/corner detection of the xBRZ filter/shaders (look at that circle-c!):

Sharpest Pixels
While "Pixellate" is the perennial favorite for this task--that is, getting the absolute sharpest pixels without having the uneven pixel sizes associated with nearest-neighbor at non-integer scale factors--some GPUs are just too slow for the many texture samples required for it. I'm not going to show any images here because there's not much to see, but the sharp-bilinear shader prescales the image with nearest-neighbor to the largest integer and then uses bilinear scaling for the remaining fractional scaling. Since it uses the GPU's built-in scaling hardware, it's practically free. In fact, you can do the exact same thing manually by putting in a pass of the stock shader at the desired integer scale and then scaling the rest of the way with bilinear (if bilinear filtering is disabled, you can do this explicitly by setting another stock pass with "don't care" for the scale factor and "linear" for the filtering method).

Monday, April 2, 2018

Epic 4G CM10.1

I have a bucket full of old Epic 4Gs, the Sprint variant of the Samsung Galaxy S which was also the last mass-produced phone with a good physical keyboard, but it has become very difficult to find software to load on them. Newer builds of LineageOS don't support it and it's pretty much impossible to find old versions of Cyanogen Mod that will run on it. On top of that, it's just too weak of a phone for any newer OSes, though it still has plenty of potential value as an audio player / digital camera / IM machine (thanks to the physical keyboard!) / child's beater phone.

Luckily, I found a cache of old CM10.1 (Ice Cream Sandwich, IIRC) plus G-apps software on one of my old phones that I still use as a digital camera at work, so I figured I'd post it here in case anyone else wants to breathe some life into their old trash-phone. It should flash onto any Epic 4G just fine with Heimdall/Odin. Download link.

Thursday, December 14, 2017

FrankenTurntable and Speaker Upgrades

I've been helping a friend of mine with his stereo recently and it got me energized to do some work on my own. First of all, I decided to finish a long-term project of mine that's been on hold since my daughter was born: assembling a turntable out of myriad spare parts, most of which I already had lying around.
The platter and mechanism came from a frustratingly crappy direct-drive linear-tracking turntable that I rescued from the trash. I bypassed all of the control circuitry and wired the power directly to the motor, so it only turns at 33 1/3 RPMs (i.e., no 45s for me), but it seems to be pretty solid and consistent at that, at least. I'm interested in trying some different platter materials at some point, but I doubt the motor has enough torque to handle anything much heavier than the one it came with.

The tonearm comes from a Technics SL-1950. I bought this one used off of eBay for about $50. I mounted it to some spare blocks of wood I had lying around and purchased some long, skinny nuts and bolts that I used to raise it to the appropriate height for the platter and get it leveled properly. I also used the wood to sandwich some female RCA jacks that I spliced onto the tonearm's own wires so that I could hook it up to my preamp using standard RCA cables (the yellow jack is the ground line).

It sounds really good and, despite looking ghetto af, it has a nice, post-apocalyptic DIY charm that that appeals to me. More importantly, though, this raw setup provides a direct line from the tonearm to the preamp/amplifier without any of the circuitry in the way that can lead to signal degradation in many more user-friendly turntables (like my LP-120 before I modded it for a direct connection, as well).

If you'd like to hear the output, it's the turntable I used to make the recordings for my cartridge comparison post.

Next up, I've been giving my Dared VP-20 tube amp a rest lately and am instead using a Lepai LP-2020TI tripath amplifier I purchased from Parts Express. It seems Lepai is no longer producing the original model, the LP-2020A+, which is a shame since it was so well-loved among audio enthusiasts, but they are making what is essentially a clone using a more easily sourced chipset (it pumps out a few extra watts, too, which is nice). It has the same clean, low-distortion sound as the original (as long as you keep the volume dial below about 11 o'clock, just like the original...) and, as much as I like my tube amp, the Lepai provides a clear accuracy that can be a refreshing change of pace from the folksy warmth of the tubes.

Finally, I overhauled my backloaded horns--which I originally fitted with some cheap but adequate drivers from MCM Electronics--with some really nice Tang-Band full-range drivers. Since the MCM drivers are only good to about 4 kHz, I had them set up on a 3-way crossover with some Bohlender Graebener Neo8 midranges. It sounded good, but I've always heard that full-range drivers running uncrossed sound more "realistic" than 2-/3-way setups.

So, I hooked the Tang-Bands up uncrossed with the ribbon tweeters wired in parallel (the Lepai can push the combined 4-ohm load just fine), and sure enough: they sound a lot brighter and more even than the crossed 3-way setup, likely due to the Tang-Band's hump above 15 kHz combined with the natural lack of sensitivity mismatching.

The Tang-Bands are supposed to be good down to 60 Hz, but they were barely usable down to probably 80-100 Hz or so (I suspect the chambers in my horn boxes just aren't large enough for the rated performance), so I definitely need my 15" subwoofer in the mix now (my old 3-way setup benefited from it, as well, but it wasn't strictly necessary). Likewise, the ribbon tweeters are supposed to be on high-pass filters for safety, but I'm pushing such a light load through them that I'm pretty sure they'll be okay.

Phono Cartridge Comparison: At95e vs Ortofon Omega

I recently assembled a franken-turntable from bits and pieces I salvaged from other systems, but one of the pieces I needed to complete it is a new cartridge. I already had an At95e from Audio Technica, which is well known and well regarded among turntable aficionados as a solid budget cartridge, so I thought I would mix it up a bit and purchase another favorite from the budget realm, the Ortofon Omega. Both of these cartridges are available for around $35-40, so I figured it would be a good, fair fight. Reviews online tend to refer to the Omega as "warmer" than the At95e, which is known as a "sterile" but "accurate" performer.

Audio Technica's At95e
For testing, I took two short recordings with each cartridge from the 'tape monitor' output of my preamp, which sends a full-output signal (i.e., bypassing all of the volume and EQ from the preamp aside from applying the Redbook boost to the phono stage) directly into the audio input of my Lenovo Thinkpad laptop. I used Steely Dan's Showbiz Kids (track 1 from side B of the first disc of Steely Dan's Greatest Hits double LP) and Dr. Dre's Nothin But a G Thang (coincidentally also track 1 from side B of the first disc of The Chronic 180g vinyl remaster). I didn't do any EQ/processing/declicking, just removed the dead space at the beginning and normalized both tracks to -1 dB because the At95e put out a slightly louder signal and we typically think louder things sound subjectively better.

The Ortofon Omega
You can download my test recordings here. (Note: these recordings are short and only include the intros of the songs, and I believe them to be covered by Fair Use). I did my testing using the Lacinato ABX audio testing software, which is free to use, listening via Audio Technica ATH-M50 closed-back headphones.

If you wish to remain impartial, please do your listening/testing before reading any further.

Ok, so first off, the results are extremely close. I think anyone would be very happy with either of these cartridges for the prices they typically go for. In simple, unblinded A/B testing, I feel like I was able to hear a consistent difference between them, mostly in the vocal midrange. The At95e sounds a little roomier while the Omega sounds very tight. Whether one would consider either to be better than the other probably depends on the words I use to describe them (e.g., roomy vs loose/sloppy, tight vs constricted). I honestly don't think I prefer one over the other, it's just a slightly different character.

In proper blinded ABX testing, that all fell apart and I wasn't able to reliably tell them apart. I did about a half-dozen comparisons and my best accuracy rate was around 67%, but more often I hovered around 50% and my confidence was always quite low.

So, there you have it. Both are good budget cartridges with no major differences as far as I could tell. I noticed no difference between them in "warmth" or "accuracy," whatever that means. You should probably take reviews claiming otherwise (e.g., suggesting one or the other is better for this or that kind of music, etc.) with a grain of salt. Feel free to leave a comment with your own ABX results.

Monday, October 30, 2017

N64 VI Filter

The N64's RDP chip includes a Video Interface (VI) stage that prepares the video for the final output. From the N64 Programming Manual:
The video interface reads the data out of the framebuffer in main memory and generates the composite, S-video, and RGB signals. The video interface also performs the second pass of the antialias algorithm. The video interface works in either NTSC or PAL mode, and can display 15- or 24-bit color pixels, with or without filtering, at both high and low resolutions. The video interface can also scale up a smaller image to fill the screen.
These functions can make a very big impact on the final image of an N64 game, and the ParaLLEl-N64 libretro core exposes the ability to toggle the postprocessing effects of this stage on and off. Turning it off nets you a few frames per second of speed but also gives us a peek behind the VI curtain:
Filtered
Unfiltered
So, you can see that the filter just barely touches the HUD elements but it does some pretty dramatic stuff to the rest of the image. It applies strong antialiasing to the outside edges of objects, which has a big, noticeable effect (so noticeable, you can see it in the thumbnail images) on Mario's hat and the silhouette of the tree, and it does some blurring that smooths out the dithering that is very visible in the unfiltered shot. On actual hardware, the blurring can be toggled off in some games (Quake II, for example, IIRC) or using Gameshark codes. I believe consoles modded with UltraHDMI or etim's N64RGB boards can also switch it off through the boards' firmwares.

Wednesday, October 25, 2017

Using RetroArch via Snappy

I've been working with some folks on trying to get a snap package up and running for RetroArch to go with our FlatPak and AppImage universal linux packages, and it's turned out to be more complicated than I expected to navigate the particulars of the packaging format combined with the restrictions of the security sandboxing.

We announced the package a couple of weeks ago but quickly got reports that users couldn't load files, they were confused as to why the package took a long time to load (only on the first launch, but they didn't know that), and more. Since updating my laptop to Ubuntu 17.10, I decided to "dogfood" the snap package, since that would be the only way I could get in front of the reports and ensure a good experience.

Since RetroArch requires a lot of stuff to look nice and function properly, we use a wrapper script that checks for the existence of that stuff and, if it's not where we expect it, it copies the stuff into the snap's user directory. Since that copying can take a long time, I decided to use notify-send to include some admittedly uninformative notices just to let the user know that nothing is frozen/broken and that we're just copying stuff in the background. The catch here is that you can't use the system's notify-send, you have to include it in the snap as a runtime dependency, under the "stage-packages" in the snapcraft.yaml recipe, like this. I tried adding an icon to make the notifications prettier and more obviously RetroArch-related, but I could never get it to actually see the icon, no matter where I stored it, so I gave up on that.

Ok, so the notifications were a nice little improvement, but we still couldn't actually get to any files to launch them, which makes the program pretty useless. For that, we needed to add the "home" plug to the recipe, like this. This plug is supposed to be auto-connected, so you shouldn't need to do anything to make it accessible to your application once it's in the recipe. However, RetroArch's non-native file-browsing meant that it tried to start in /, which is inaccessible (and in fact, totally invisible) to the snap (and if your snap starts you in an inaccessible directory, you can't ever get out of it), so I added a line to my wrapper that pre-populates the user's retroarch.cfg config file with a line telling it to start in the home directory, where we should have access. I tried using $HOME and ~/, both of which just sent me to the snap's home directory instead of the true home directory with all the files -_-. The solution I found--which is pretty crummy but whatever--is to use a relative path that points to one level above the snap package. That is, ~/../../../

Similarly, I couldn't reach my network shares, which I mount in /media (despite adding any plug that seemed even vaguely related to such a thing to the recipe), so I had to move my mount points into my true home directory and use those same relative paths to everything, e.g. ~/../../../smbshare/Emulation/BIOS for my 'system' directory. Once the mount point is in my true home directory, I could probably put symlinks into the snap package, as well, to avoid the silly relative paths.

The last major issue I ran into was that the *.desktop launcher that shows up when you search for programs in the sidebar kept complaining about not having an "exec" line and then failing to launch because of it. This one was super-confusing because our snap has a *.desktop file (it lives in $SNAP/meta/gui), and that file definitely has an exec line. It turns out that, during installation, snapd generates the *.desktop file that the OS actually looks for and stores it in /var/lib/snapd/desktop/applications. This file is based on the *.desktop included with your program, but if the exec line isn't just like it expects, it will strip it out entirely and not give you any indication of why. Initially, our *.desktop file pointed the exec line to the retroarch.wrapper script that does so much work for us, but snapd didn't like this and rejected it until we switched it to just "Exec=retroarch", which isn't the name of the actual executable but rather the name of the snap itself. It still launched the wrapper script, since that's what our recipe points to, so we're all set.

Since we need to use our script when we launch from a command line, as well, we made sure to end it with $*, but this has a couple of problems that experienced scriptors will spot immediately. First, it's not escaped, so any spaces in file names will break it. Second, it will only accept a single argument, which isn't going to work for us. So, I changed it to "$@" and all is well.

Now, the only issues left that I know of are: 1.) the wrapper script has our nice invader icon, which shows in the sidebar while the script is running, but once it dies off, the icon goes with it and the actual program just has an ugly question-mark/no-icon-found icon in the sidebar and 2.) the snap can't load any dynamic libraries that live outside of its domain, so I can't conveniently compile a test core and then launch from command line to test it with the -L switch. #1 isn't a big deal and #2 probably isn't possible to fix, so it is what it is.

Analytics Tracking Footer