Thursday, June 7, 2018

Trading Moire for Noise in Shaders

Note: the ugly artifacts we're trying to deal with in this post also happen whenever you up/downscale images, so be sure to click the thumbnails to view at full resolution.

A lot of folks like to apply a pincushion/curvature effect to their emulator image to try and capture a bit of the old CRT TV curved tube effect. This can be a problem, though, when paired with a scanline effect, since the curvature introduces an aliasing artifact on the scanlines known as a "moire pattern":
This is a worst-case scenario, used for illustrative purposes.
Notice the ugly pattern fanning out from the middle of the outside edges of the screen
This problem comes up a lot in virtual reality applications, where content often runs through a pincushion effect to compensate for the lens distortion of head-mounted displays, which then leads these same ugly patterns to crop up on any design with parallel/converging lines.

Graphics programmer Timothy Lottes (author of the popular FXAA algorithm and a lovely public domain CRT shader, among others) was working on ways of dealing with the aliasing/moire problem for VR and published this shadertoy showing how to hide it by introducing jitter/noise in where the texture is sampled. Turns out that same strategy can be used to mitigate our scanline moire.

When applied to an actual game image, this:
becomes this (caution, big animated gif; the noise effect doesn't really work in still images):
You can see that the noise is concentrated along the same areas where the moire pattern was visible before, but it's much less obtrusive and sort of melts away when viewed at a distance.

When curvature is added to an existing, normally flat CRT shader (Themaister's crtglow-gaussian shader, one of my favorites), we go from this:
to this, with the noise/jitter-based mitigation:
In this example, the noise also adds a touch of analog warmth/sparkle to the CRT effect, which I like.

Here's the code snippet that does it (all copyrights belong to Mr. Lottes):
This code can be added to many CRT shaders by wrapping the shader's fragment texcoord declaration with the moire_resolve() function to add the jitter/noise and then wrapping that with the Warp() function to add the curvature. You can see an example of where I've done exactly that in the crtglow-gaussian shader here to create the screenshots above.

Wednesday, May 30, 2018

RetroArch Mirror Mode

Sega recently updated their Mega Drive & Genesis Classics emulator collecdtion on Steam to include a fun little feature known as "mirror mode," which flips the game image and controls to be a mirror image of what we're used to. This adds a really surprising challenge, since it breaks all of our muscle memory (including the deeply ingrained "run to the right!" imperative).

This has been possible in RetroArch for a very long time, but it requires twiddling a few esoteric options that may not be familiar to a majority of users, so I figured I'd run through the process briefly.

Step 1: Flip the screen

As with most of the fun video tweaks in RetroArch, we accomplish this through a shader. So, with some content loaded, bring up the 'quick menu' and scroll down to 'shader settings'. On that screen, increment the number of shader passes from 0 to 1 and where it says 'shader #0 N/A,' navigate to the image-adjustment shader located in the 'misc' subdirectory of your shader flavor of choice. I'm using slang shaders here, which are compatible with the Vulkan and D3D11/12 video backends. You can add additional shader passes after the image-adjustment shader, if you like.
Once the shader is selected, go up to the top of the shader menu and hit 'apply changes', then skip down to the 'shader parameters' submenu and you should see a ton of options for tweaking the image. Down at the very bottom, you should see 'flip horiz axis' as the second-to-last option. Set it '1.0' and you should see the screen mirror.

Step 2: Flip the controls

From the shader menu, hit backspace or 'cancel' to return to the 'quick menu' and look for the 'controls' submenu. Here, you can change which of your physical or retropad buttons trigger which core functions. So, scroll down until you see entries for the D-pad. In my case, we have 'Left D-pad (key: left)', to which is assigned D-pad Left, and 'Right D-pad (key: right)', to which is assigned D-pad Right. Simply swap those (as pictured) and you're all set.
Now, we could save a remap file to be automatically loaded whenever this core or game is loaded, but I don't want my controls to be mirrored indefinitely, so I'm not going to do that, and this setting will simply get wiped out when I 'close content' or 'quit RetroArch'.

Bonus Step 3: Flip the audio channels

This is not vital, but if you want to get the full mirror effect, we'll need to swap the audio channels so that the sound effects follow our mirrored video and controls. This is achieved using RetroArch's fun, powerful and oft-overlooked audio DSP system. The pre-installed 'panning' DSP has the ability to swap the channels, we just need to create a preset file that tells it how to do it. So, open up a text editor and paste in these contents:
filters = 1
filter0 = panning

# Swap left and right channels:
 panning_left_mix = "0.0 1.0"
 panning_right_mix = "1.0 0.0"
Save this file as something descriptive and change the file extension to 'dsp' (mine is named Mirror.dsp) and then move it into your RetroArch installation directory, under [RA dir]/filters/audio. Then, back out of the 'quick menu' and go to 'settings' -> 'audio' and scroll down to the 'Audio DSP Plugin' option, where you can select your newly made DSP preset:
 

Getting back to normal

Ok, that was fun, but I don't want to play like that forever, so it's time to put things back to normal. For the shader, go back to the shader options menu and navigate to the number of shader passes. Decrement it down to 0 (or hit the spacebar on your keyboard or 'start' on your gamepad) and then go up and 'apply changes' and you should be un-mirrored. Now, for the audio, go back into 'settings' -> 'audio' and navigate to the 'Audio DSP Plugin' option and press spacebar on your keyboard or 'start' on your gamepad to remove the plugin. As long as you didn't save the input remapping in the 'controls' menu, they should return to normal as soon as you 'close content' or 'quit RetroArch'.

Wednesday, May 9, 2018

Building an SNES Controller

This was a fun little project that I intended to log in great detail but I just didn't really take enough pictures, so I realized too late that it's more of a "draw the rest of the fucking owl" situation. Oh well, here's what I ended up with, and I'll follow up with some info on how I got there:
My giant SNES pad with original pad for scale reference
It's a 6:1 scale SNES/SFC gamepad built from scratch. Unlike the other oversized gamepad projects floating around online, I don't have a 6-figure woodworking shop (and I'm not a good carpenter anyway), so I used manufactured arcade buttons instead of rigging up funky homegrown button/dpad mechanisms, and I built the internals using a breadboard and a couple of shift registers instead of padhacking an original SNES pad (those things are getting expensive these days).

I had originally planned to make the size an even 10:1 scale but after doing the math, I realized the resulting pad would be over 6 feet across and wouldn't be practical to actually use (i.e., like most of the other oversized gamepad projects floating around online). I had chosen 10:1 because SNES pad buttons are right at 10 mm in diameter and you can purchase humongous 100 mm arcade buttons on Amazon/eBay, but they also sell 60 mm buttons, which results in a much more reasonable 6:1 scale.
I found this dimensioned image online but it seems to have disappeared so I'll rehost it for others to benefit from.
Once I got the scale figured out, I cut the outline of the pad shape out of a piece of particle board I had left over from a previous project. I don't have a router and a circle jig, so I used a jigsaw and fashioned a compass out of a pencil and some string to draw the round parts:
For the internals, S/NES controllers are exceedingly simple, consisting of nothing but a couple of 8-bit shift registers. I happened to have 2 CD4021Bs lying around from a previous project and figured I'd give it a shot. This schematic shows up various places online and was very useful for getting everything wired up to my breadboard:
And here's what it looks like all wired up:
The only part I didn't make myself is the actual controller port plug, which I took from a newly manufactured SNES extension cable.

I used terminal blocks to make it easier to swap things out in the future and to reduce strain on the breadboard connections, which are the weakest link in the chain. The terminal blocks also came with bridges (the red-rubber thing on the one at the bottom-left of the image) that were useful when running voltage lines out to the button LEDs.

I left the back open and just built a little frame around the wiring. I may go back and put acrylic or another piece of wood over it, but I'm okay with it as is for now:
You can also see the L and R shoulder buttons, which are just the same 60 mm buttons used for the face buttons (the button sets come with 5 buttons and I ordered one additional one for a couple of extra bucks on eBay). The dpad buttons are also 60 mm buttons, but they're flat instead of convex:
Testing the button LEDs. You can get a good look at the flat dpad buttons. Still lacking some of the paint, as well.
It controls surprisingly well and is sort of like a Playstation controller with the separate directional pads. The start and select buttons are just regular ol' 30 mm arcade buttons. I would have liked to do something that looks a little more authentic but there just aren't any off-the-shelf long, skinny buttons.

Some day, I may go back and fabricate a small dpad to lay over the individual buttons and/or rig up something over the start/select buttons, but I doubt it, since they work fine already.

Anyway, here's my 3-yr old daughter and me playing some Donkey Kong Country on it:
She still doesn't really get video games, and her fine motor skills aren't really good enough for a standard-sized gamepad (which isn't really designed for her toddler-hands anyway), but she likes pushing the buttons on the oversized pad and having me control movement lets her focus on a single action, like jumping. I can also call out the color of the button she needs to press, which helps her work on her color mastery.

Anyway, that's it. If you have any questions, hit me up in the comments.

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.

Analytics Tracking Footer