PlainOldPants's Shader Presets

2025-03-27

This is my latest NTSC CRT color emulation setup, which tries to approximate the following CRTs: Toshiba FST Blackstripe CF2005 (1985), RCA ColorTrak Remote E13169GM (1989), Sony Trinitron KV-20S11/KV-20M10 (plus at least one unknown Japanese variant with slightly different settings) (1994), and Panasonic CT-36D30B (2000) with its “Normal” color temperature setting. The non-Sony ones are based on data that I sampled myself, while the Sony ones are from data found online.

The catch: The resulting images are much darker than they need to be. If you try using it with a CRT shader, it’ll become even darker. For this reason, I’ve been using a basic bilinear filter lately.

Pay special attention to the US Sony one. My previous shaders have attempted to emulate that specific CRT’s colors, but this new implementation is much more accurate.

Note: For Genesis, you must use the BlastEm core with this shader. That emulator outputs the original hardware’s RGB levels. Some of my previous shaders allow you to correct Genesis Plus GX’s output, but I forgot to include that this time.

Download and installation

Download here: https://www.mediafire.com/file/1gmfye6js9t5gtv/crt_color_2025_03_26.zip/file

Unzip into any folder, preferrably the “shaders” folder in your RetroArch directory.

Move the .pal files into your RetroArch system directory. These are NES color palettes. To use one, make three copies of it called “nes.pal”, “custom.pal”, and “MesenPalette.pal”. Then, in the emulators FCEUmm, Nestopia, and Mesen, change the color palette to “Custom”. To use with a standalone NES emulator, look up that emulator’s own instructions.

The following instructions are for consoles OTHER THAN NES ONLY:

In RetroArch, make sure your driver for video is “vulkan” or any driver that is able to run slang shaders. Changing this setting requires a restart. Most recent PC should be capable of this. Most console ports of RetroArch are not able to run slang shaders, so they’re not able to use my shaders at all. (My NES palettes will still work; in fact, they work on emulators outside RetroArch too.)

Load any game as usual. (Note: For Genesis, you must use BlastEm with this shader. That’s my mistake.) In the Quick Menu, choose “Shaders”, and choose “Load Preset”. Navigate to wherever you unzipped crt_color_2025_03_06, and you should now see the files starting with “P68k” which each correspond to a different CRT. Pick whichever one you like–I recommend starting with P68k_SonyJP_1994. After loading it, go to “Shader parameters”, and feel free to change only these four settings to whatever you like best:

You are recommended to change ONLY these four settings

  • Enable NTSC color correction (a.k.a. red push) – Turning this off is equivalent to RGB-modding a CRT or using YPbPr Component (if available), which bypasses the NTSC color corrections.
    • You may only disable this on the 2000 Panasonic CT-36D30B. This is the only CRT where you can bypass the “red push” on the real hardware because it has a YPbPr Component input, which the other CRTs don’t have.
  • (Default=0.0) End-user Tint knob rotation – You are very highly encouraged to change this to whatever you like best.
  • (Default=1.0) End-user Color knob rotation – You are very highly encouraged to change this to whatever you like best.
    • Prior to the late 90s, everyone always had to mess with the Tint and Color settings on their TVs to make the image look acceptable, but it never would look perfect. Everyone was happy that their TV just worked.
    • The defaults in my shader approximate the broadcast standard, but consumer TVs before the late 90s often had totally wrong defaults.
    • In addition, game developers often didn’t have the best defaults either. In fact, many developers used RGB (except for the NES).
  • Approx. Gamma (recommend 2.2) – This is the “Brightness” knob in disguise. You are very highly encouraged to change this to whatever you like best.
    • “2.2” is the actual NTSC standard, but 2.0 gives the best detail in dark areas, while 2.4 later appears in the BT.1886 standard. In general, I recommend 2.2.
    • Note: Do not confuse this with the other setting called “(Dual) CRT’s actual gamma”. This is best left at 2.0.

More details about how this works

The most important part of this by far is the improved KV-20S11/KV-20M10 approximation. Unlike the other CRTs here, I have never owned either of these Trinitrons, so they are being approximated solely using information from a few different sources on the internet. All my previous uploads, from before I owned a colorimeter, assumed these CRTs used illuminant C, the standard whitepoint for NTSC broadcasts. I have since discovered that the correct whitepoint is most likely 9300K+8MPCD, the standard whitepoint for Japanese broadcasts, even though the CRT is manufactured in the USA. In fact, most CRT TVs have much higher color temperatures than the standard. (More details here.)

That means, my releases from before December 2024 (which feature signal artifacts and “sanitized” presets) need their whitepoint changed to a “custom x, y” with x=0.2838, y=0.2981 (shown as 2.84 and 2.98 in the settings). That fixes the issue with them being extremely pink. While you’re at it, you should fix the demodulation settings: change the R-Y/G-Y/B-Y auto-sync to “off” (or -1), and change Color/Saturation to 0.975 and Tint/Hue Rotation to either positive 9 or negative 9, whichever one looks correct. Feel free to adjust these two Color/Tint settings to your liking, but know that these are the defaults for US NTSC.

For the other CRTs, these are ones I currently own in real life, and I have used an X-Rite i1Display 2 colorimeter to measure them. I have completely re-sampled the Toshiba CF2005, RCA ColorTrak Remote, and Panasonic CT-36D30B, and I’ve done it more accurately and carefully this time. (Note: The CF2005’s white balance couldn’t be taken directly because of its poor condition, so I had to make an educated guess: The red and green color channels both are very closely in-sync, but the blue channel is out of sync. That means the correct whitepoint must be close to this specific red/green ratio. Assuming that point is on the daylight locus, it’s about 8300K.)

Another improvement is that the Contrast, Brightness, Color, and Tint knobs are automatically calibrated for you. By default, the shader approximates the 1953 NTSC standard in the CRT’s intended region. You are still allowed (and encouraged) to adjust the Tint and Color knobs by yourself easily. Brightness is adjusted using a different setting called “Approximate gamma”, which is really a brightness setting. (That’s not to be confused with “Actual gamma”, which is the CRT’s real gamma constant–Don’t adjust “Actual gamma” unless you know what you’re doing.)

I have improved the EOTF too. When looking at sampled data, it’s easy to fool yourself into thinking your CRT is around 2.4 gamma, or that something is wrong with your setup. What seems more likely to me, just based on the data from my colorimeter, is that CRTs tend to have a gamma somewhere between 1.9 and 2.1, and that the brightness tends to be lower than the standard black level to approximate the standard 2.2 gamma. Hence, for this CRT emulation, I’ve set a gamma of 2.0 and a brightness of about -0.08 for all CRTs. In the shader’s settings, you can set the CRT’s real gamma and the desired gamma yourself.

I’m using ChthonVII’s program called gamutthingy for simulating the phosphor gamuts with state-of-the-art gamut compression mapping. For more information on that, see https://github.com/ChthonVII/gamutthingy

Something not emulated is how the 1980s CRTs have very reflective screens. Even when powered off, the screen is still a light gray. This will have to be added in an update. This also isn’t emulating these CRTs’ uncalibrated grayscales either; the white balance is constant throughout the grayscale in this shader.

NES palettes for all models except the Sony Trinitrons have been included. The Toshiba 1985 and RCA ColorTrak 1989 ones are improved, but the Panasonic 2000 ones are the same ones that I’ve already posted.

As a final note: I still apologize for not posting any video signal improvements, after months of promising.

10 Likes

2025-04-24

Minor update to my previous shaders, but the default settings look very different from before. I’m releasing this update a bit hastily without extensive testing, so beware of that. https://www.mediafire.com/file/ri1x3pk8xveklrq/crt_color_2025_04_24.zip/file (Modified 22:04 UTC to remove “Auto” chromatic adaptation, which is bad and has no use case.) Few or zero true improvements to accuracy have been made, and the previous version can mostly appear similar to this one just by adjusting settings.

Usage and installation instructions are unchanged from the previous post, except that this new version doesn’t include NES palettes.

  • Changed the default Tint, Color, and Brightness settings to look better. This change looks much better than my previous version’s defaults, at least in my own opinion. (Though, you were encouraged to change those to whatever you like, and I still encourage that now.)
    • In short: The previous version was calibrated for actual NTSC video (with one small issue), and this new version is calibrated for video games.
  • Added “1997ish” presets that use the well-known Sony CXA2025AS in US and JP mode. This really should’ve been included from the start; there was no good reason for omitting it.
  • Added a “split” SMPTE-303M test pattern. This pattern can be used along with the “Goal gamut” setting to help set the CRT’s Tint, Color, and Gamma to your preference. (Really, I made it to try to reverse-engineer the way that these CRTs are intended to decode color, and to try to determine how typical end-users would likely set their settings while playing video games.)
  • Updated the 1985 Toshiba CRT’s whitepoint to a newer estimate that should be better. (It still might not be that reliable.)

For some more details about what’s changed with the default settings:

  • The previous version had the CRT’s real gamma at 2.0, but the brightness knob was darkened to approximate 2.2 gamma. The rule of 2.2 gamma was never enforced, and values ranging from 1.8 to 2.5 were used (and I won’t cite a source for this). This new version uses a straight 1.925 gamma with perfect brightness, which is more like you’re playing in a well-lit room, and this is also a match both for my mostly-intact 13-inch RCA ColorTrak Remote, as well as for the later SMPTE-170M/240M standards.
  • The previous version set Tint and Color to match the color Orange in standard 1953 NTSC, but I took chromatic adaptation into account, which I now think is wrong and isn’t what most people did. This current version sets Tint and Color on a 1.925-gamma CRT to match a flesh tone in a 2.4-gamma Japanese RGB monitor, without performing any chromatic adaptation. 2.4 is for CRTs whose brightness is calibrated in a dark room, and it appears in the standard BT.1886.
  • To make non-Japanese NTSC games look better, change the setting “Goal Gamut” to 2.
More details about skipping chromatic adaptation (Please don't click this)

The previous version accounted for chromatic adaptation for these reasons:

  1. These CRTs are from the mid/late 80s to the 2000s, and chromatic adaptation was absolutely not an unknown concept. By the time that CIELAB was published in 1976, it had been decided that XYZ-scaling sufficiently approximated chromatic adaptation for that purpose. By 1985, the Bradford method was published, and this method still is used to this day in commonly-used software such as ArgyllCMS, Adobe Photoshop, and (correct me if I’m wrong about how this works) Windows 11’s stock color management.
  2. Performing chromatic adaptation in a SMPTE-303M test pattern had shown that orange, blue, and other critical colors were matching great at the expense of green being a little bit too yellow. It looked believably like this is what it was supposed to be.

My reasons for not accounting for chromatic adaptation in this update are the following:

  1. Documents such as “The White Color of Television Receivers” by Donfrio, Hess, and Sember and Toshiba’s patent US5301017A both seem to suggest that whitepoints bluer than C/D65 are just there for technical reasons and for making black-and-white footage look right (due to old black-and-white CRTs having very blue/green whites), but nothing ever suggests that anyone would ever genuinely want color video to visually appear like it’s illuminated by a bluer whitepoint. Perhaps they might decode the saturated colors in a way that still looks like it’s illuminated by D65 or C.
  2. I got a spare half-hour and finally found a PDF for this paper that had been shared with me last year. (Really, it was hiding in plain sight.) It is from 1966 (predating all CRTs in this thread by at least 19 years), and it explains just one method for deriving the corrective R-Y/G-Y/B-Y demodulation. The paper shows how NTSC color can be almost perfectly represented at D65, even with care taken to make specifically chosen critical areas more perfect. However, it also acknowledges that many CRTs have a nominal white near 9300K (in this case specifically referring to 9300K+27MPCD, x=.281, y=.311, not to be confused with 9300K+8MPCD), and as such, it performs the same derivation for this too. This part is the kicker–Do you remember what I said earlier about no one genuinely wanting color videos to look like they’re illuminated by 9300K? This paper just straight up derives a matrix that perfectly represents a flesh tone and a green (and thus everything in between them) as if illuminated by the standard illuminant C, but it moves the base white from C to 9300K at the expense of everything else being screwed up. (Something not mentioned is that they could’ve experimented with adjusting the luminance of this 9300K whitepoint independently of the green/flesh luminances, which could at least make the rest of the gamut look slightly better.)
  3. Now that I’ve tried matching the CRTs in the 303M test pattern without accounting for chromatic adaptation, the Japanese-branded American NTSC CRTs (Toshiba and Sony), when used with a test pattern of American standard NTSC colors, appear to be doing exactly what that paper described, making green through flesh look correct, moving white to something bluer, and messing up other things, although the whitepoints they picked mess things up differently than 9300K+27MPCD. My 13-inch American-branded (RCA) one that I keep on my desk in my university dorm, which is closer to D65 but really more like blackbody 7500K (consistent with Dogway’s claims that D65-region CRTs were typically around ~6900-7100K and sometimes ~7500K in practice) makes almost all of the American NTSC test pattern colors look nearly right, consistent with how this paper demonstrates how CRTs with the standard white have vastly superior colors. Similarly, the Japanese Sony CRT, when used with a test pattern of Japanese standard NTSC colors, leaves everything mostly intact like it had been broadcast, since the whitepoint is already at 9300K and doesn’t have to be moved. (I can’t tell what’s going on with the Panasonic one at all.) Even though these tests are done hastily, I believe for now that these CRTs’ color corrections were made without chromatic adaptation.
  4. In general, performing chromatic adaptation just doesn’t preserve the original image that well in my opinion, based on my own experimentation.
5 Likes

2025-04-26 - White Trash

This is a new NTSC CRT color shader, called white-trash, which I spent some hours making over the past two days. It has a similar purpose to my shader from two days ago.

Unlike the previous release, this one isn’t based on any specific TV. Instead, this one tries to be a generic average of common American TVs. There isn’t as much real data backing this one up, so take it with a grain of salt.

The shader works like this:

  • Your TV is made to decode 1953 NTSC video that’s broadcast over the air with a gamma of 2.2. It also is made to change the white point to ~8700K daylight without changing the red/yellow/green range of colors, but at the expense of other colors becoming bluer. (This is why it’s called white-trash.)
  • The game you’re playing is assumed to developed on a CRT in Japan over an RGB connection with a gamma of 2.4.
  • You turned your TV’s brightness up higher to make dark things easier to see, resulting in a gamma of 1.925. You change your TV’s color and tint to make the game look acceptable, but it’s still not perfect because your TV is made for watching NTSC video broadcasts, not Japanese RGB.

EDIT: There is a bug. This only works if the broadcast white is set to illuminant C.

Download here: https://www.mediafire.com/file/4gg2npxm3atkvjc/white-trash-2025-04-26.zip/file and install by extracting it into RetroArch’s shaders folder.

The shader has the SMPTE-303M testchart built in so that you can see what it’s doing. In each box, the left half is what the color is supposed to look like, and the right half is how the TV displays that color. These ones are set to automatically match the brightness of both halves so that you can just compare the color itself.

Here’s one showing how colors meant for sRGB (really EBU) 2.2 gamma get changed on this CRT. In other words, this is comparing what an emulator typically shows to what an average American TV shows. Notice how gray, cyan, and some greens all become bluer. Other than that, it’s not too different.

Here’s one comparing what many Japanese developers saw (on the left halves) to what the average American consumer (according to this shader) saw (on the right halves). Notice how the grays aren’t changing much because both TVs used similar white points, but there is still some change elsewhere. Like before, it’s not too different.

The previous upload from 2024-04-24 had an SMPTE-303M test pattern built in too, so for comparison, here’s how the Sony US 1997ish preset from two days ago affects sRGB colors:

and here’s how that same Sony US 1997ish preset affects the colors that Japanese developers saw:

Comparing these, I can’t say for sure that “white-trash” is that close to original hardware. That’s even though I coded white-trash specifically based on what I assumed many popular brands must have been doing. Even so, these different TVs’ colors are so slightly different but similar to each other that I’m not sure that it’s worth it to keep experimenting with it either.

Anyways, I am satisfied with the colors for now. The next thing to work on is composite video signal artifacts, the thing I’ve been meaning to update for at least six freaking months. At this point, every possible reason for me to wait on that is gone.

8 Likes

Turns out, there actually are a couple more reasons to wait on working on the composite.

Japan RGB shader pack

Over the past couple posts, I’ve stated that I’m color-matching the old TVs’ settings against what I believe to be the most common intended colors for Japanese-developed games, yet for some reason, I haven’t actually ever posted a shader for the Japanese intended colors.

This pack just does Japanese RGB straight-up. (Keep in mind, not all Japanese CRTs looked quite like this. There is absolutely no definitive correct answer, as all CRTs were a little different from each other.)

Download here: https://www.mediafire.com/file/4er1xoema7v8v6i/crt_color_jp_rgb_sony.zip/file

Details

The above shader is based on Sony Trinitron P22 phosphors, a white point of 9300K+8MPCD (x=0.283, y=0.298), and an EOTF of either 1.934, 2.2, or 2.4 gamma. Many CRTs in Japan had phosphors close to these Trinitron phosphors, and there is also a Japanese phosphor specification described in ARIB TR B9 v1.0 (1998) that looks similar to this. 1.934 gamma approximates the SMPTE-170M/240M and Rec. 709 standards, and is probably closer to what more end-users saw if they turned up their brightness for a well-lit room. 2.2 is from sRGB, the same as the monitor you’re currently using. 2.4 (from BT.1886) or 2.5 (just a commonly shared number) happens if you carefully set your brightness in a dark room. (With a little more time, I could use BT.1886 and do a regression to approximate those gammas, but I’ve chosen to just directly use those gammas to save my time. This post is being done in more of a hurry.)

Dogway’s Grading Shader, which has existed for a long time, is intended to show color as seen on Japanese developers’ professional monitors. The shader’s main flaw is that it has to perform gamut compression in real time, and it isn’t able to do a great job at that. ChthonViI’s program, gamutthingy, solves that problem by precomputing a full LUT in advance with much better gamut compression mapping.

There are some aspects of gamutthingy that I don’t fully agree with at the moment. First, its EOTF uses specific real-life black and white levels in cd/m^2 and sets up the BT.1886 Appendix 1 EOTF function around that. I would much rather keep the EOTF’s white fixed at 1.0 and pick a black level such that the EOTF approximates the 2.4 gamma found within that same standard. Second, gamutthingy’s default behavior is to perform chromatic adaptation from the CRT’s whitepoint to sRGB’s whitepoint, but I would rather keep the original CRT whitepoint intact. In fact, I’m not 100% certain of this, but I might rather have chromatic adaptation never be performed, as if the content being displayed is meant to appear to be illuminated by D65 even though the CRT’s white point is something different. Third, when CRT emulation is in use, you’re limited to using the BT.1886 EOTF, when I might rather use an alternative EOTF ripped from my own CRT, especially with close to a gamma of 1.925-ish. Recently, I found that regressions of the form (ax+b)^(cx+d) do a very great job at matching a sampled EOTF, so I am strongly considering making a custom EOTF from a real CRT.

Simple test pattern shader pack

I’ve been putting built-in test patterns in my shaders for a very long time now. I figure that other shader and preset authors might benefit from having them too.

Download here: https://www.mediafire.com/file/stgl5oo901ncqbb/test_pattern.zip/file

Using this is simple. Load the RetroArch shader that you want to test, prepend the “test-pattern-prepend” preset, and (optionally) append the “test-pattern-append” preset.

The test patterns included are:

  • Three kinds of stepped color ramps:
    • Brightness scales for primaries, secondaries, and white
    • Saturation scales for primaries and secondaries
    • Hue rotation between primaries and secondaries
  • Full HSL spectrum
  • HSL spectrum with primaries and secondaries widened
  • All NES palettes from the Mesen, Nestopia, and FCEUmm LibRetro cores, and from MiSTer.
    • Some of these palettes weren’t originally made with de-emphasized colors. For these palettes, emulators have to make their best guess for what the de-emphasized colors look like. This test pattern includes Mesen and Nestopia’s de-emphasized colors for those palettes, but not FCEUmm’s de-emphasized colors. For those palettes, I am also including generated .pal files with the de-emphasized colors included, for use in other NES emulators or NESRGB mods.
    • Some palettes from Nestopia are not hard-coded but are instead generated inside the emulator. For this reason, Nestopia’s Sony CXA2025AS US and JP palettes both look different from the ones in other NES emulators. I am including these both in the test pattern and as .pal files for use in other NES emulators or NESRGB mods.
    • I wasn’t able to open full_palette.nes in FCEUmm, so I had to extract FCEUmm’s palettes without de-emphasis at all. Anyways, FCEUmm’s default palette is now available as a .pal file in this release.
    • The MiSTer project has this large listing of 262 NES palettes as .pal files. I have included all of these in this test pattern shader.

I have chosen not to include the SMPTE-303M pattern because few other people here have a use for it. The pattern only makes sense in cases where you already know what you want something to look like, and you are trying to match that thing. Hence, you would have to pick several specific colors out of different games and arrange each in that pattern. At that point, it just makes more sense to use images from actual games as your test pattern.

These test patterns make it easier to tell if a shader preset is doing something weird. For instance, if you run this against Megatron (in shaders/shaders_slang/hdr), you can see that some of the SDR presets have blue getting too bright, which causes some detail to be lost. This can be fixed by reducing the contrast.

There is one major problem with using test patterns. Some shaders, such as the afterglow in crt-guest-advanced, take pixels from the original game’s output, bypassing any shaders that are prepended before it. This results in the test pattern getting mixed with the game’s image. As such, with shaders that work like that, you shouldn’t use what I’m linking below. I suggest instead using either the 240p Test Suite (preferrably on consoles like SNES, PS1, or Wii) or the image viewer LibRetro core. (I have also seen a window-caster core posted elsewhere, but I have not tried it before.)

Here’s what that looks like. These two screenshots are with an older preset by sonkun. Notice that the status bar from NES Battletoads is glowing near the top of the screen, even though the image being displayed is a test pattern. Also, notice how magenta shifts hue as it gets brighter, and both cyan and blue reach a limit at their brightest points. To me, it looks like sonkun was purposely keeping the colors as bright and colorful as possible, so much so that compromises needed to be made in these areas. That’s in contrast to other presets on this site–including my own–that achieve better accuracy at the expense of darkening the screen.

And lastly, there are some shaders that aren’t compatible with the appendable test pattern. Here’s what happens if I append the appendable test pattern on MegaTron:

Wow.

Sony CXA2025AS palettes

The CXA2025AS palettes in current NES emulators are all still using D65 for white, but the CXA2025AS is meant to be used with Sony Trinitron phosphors at 9300K+8MPCD (or at least something very close to that). I’ll definitely have to post new CXA2025AS palettes with that taken into account.

Point is, I’ll finally do video signal stuff after I address that Sony CXA2025AS issue.

6 Likes

This is useful, why don’t you submit the test patterns with a PR to the official slang shader repo?

2 Likes

2025-05-29 - NES and SNES composite video shader

I’m writing this post in a bit of a hurry right now, so I’m sorry about the lack of screenshots or details.

This new NTSC video shader supports NES and SNES only, and it is both more efficient and (by default) more accurate than patchy-ntsc. Neither the SNES nor NES signal simulations are perfectly accurate, but it’s a good balance. The biggest improvement is that I’ve designed the filters carefully to match the original NTSC specification, unlike patchy-ntsc where I tried (and somewhat failed) to visually match my original hardware.

This also includes some of my latest and best work on CRT color simulation. I’ll post more details later, but I’ve had some breakthroughs with NTSC color recently. In this shader, instead of doing a full NTSC color simulation, I’m doing an approximation that’s made from reverse-engineering the behaviors of existing decoders, which I’ve been able to reverse-engineer much more effectively using a new program of mine. I’m planning to post about this on the nesdev forums too and cooperate with those people to make more accurate NES consumer palettes. Of course, SNES is affected by this too.

I highly encourage playing around with the shader’s settings. It is designed for you to mess with the settings, and it’s much more accessible than patchy-ntsc was.

Important: For the NES version, change your emulator’s color palette to “Raw” (and if there’s no “Raw” option, use a different core). If you are using FCEUmm, please update to the latest version to fix a bug with the raw palette.

Download here: https://www.mediafire.com/file/inkup1cxqye8c6y/patchy68k-1pass-2025-05-29.zip/file

Updated version to improve SNES performance and easily darken over-saturated reds: https://www.mediafire.com/file/u0c981wllep9a2q/patchy68k-1pass-2025-05-29-r2.zip/file

Update to add Battletoads / Battletoads + Double Dragon phase cycle and the options to disable NTSC color and all gamma correction. https://www.mediafire.com/file/qlwkoqs77hdx1nb/patchy68k-1pass-2025-05-29-r3.zip/file

Update to add “2 phase” and “1 phase” options and fix some bugs: https://www.mediafire.com/file/jvbdtlutjmpkvlz/patchy68k-1pass-2025-05-30.zip/file

After a little more work on this, I plan to submit a PR so that you can just download it in RetroArch as usual.

I’m planning to try at the Genesis/MegaDrive signal (and perhaps a more accurate SNES signal too) in the near future, but I’m dreading it very much. The problem is in the way that the console filters its composite video using LC circuits. The easy part is solving Kirchoff’s laws, but the problem is that the shader has to perform a lot of iterations across multiple passes to be able to simulate that effectively. That’s going to be heavy on performance for sure, so we’ll have to just hope that it’ll be worth the effort it takes to make.

Edit: The approximate NTSC color is temporary-ish. I will later add support for a more faithful simulation using LUTs from gamutthingy by Chthon, but since doing that locks in the settings, I’ll be keeping the approximate one as an option that’s easy to customize.

5 Likes

Very nice evolution in speed! I didn’t test much. I have only one thing at first that bothered me: it’s very dark! I only tested the snes preset, and had to increase the contrast to 1.0 to get something playable.

I’ve seen the Contrast at 1.0 only works using Device 1. For Devices from 2 to 9, if you increase Contrast above 0.50, the reds clamp someway. So, you ends up with a very dark picture.

Is there a way to control the red push as the first version? It may be accurate, but I can’t remember it was so red when I played in the 80’s or 90’s, or even now in my CRTs (even on composite cables).

Overall, it looks very analogical, real and alive. Congrats!

EDIT: Nevermind the red push thing. I just found the param that desaturate the reds!

EDIT2: Here’s a useful preset I’ve got running with crt-hyllian-new-mask. I had to descrease saturation and increase contrast plus tweaking the red push param to decrease clipping:

preset patchy-new-crt-hyllian-new-mask
shaders = "6"
feedback_pass = "0"
shader0 = "shaders_slang/ntsc/shaders/patchy-ntsc/p68k-fast/p68k-fast.slang"
filter_linear0 = "false"
wrap_mode0 = "clamp_to_border"
mipmap_input0 = "false"
alias0 = ""
float_framebuffer0 = "false"
srgb_framebuffer0 = "false"
scale_type_x0 = "source"
scale_x0 = "2.000000"
scale_type_y0 = "source"
scale_y0 = "1.000000"
shader1 = "shaders_slang/crt-hyllian-new-mask/shaders/support/multiLUT-linear.slang"
filter_linear1 = "false"
wrap_mode1 = "clamp_to_border"
mipmap_input1 = "false"
alias1 = ""
float_framebuffer1 = "false"
srgb_framebuffer1 = "false"
scale_type_x1 = "source"
scale_x1 = "1.000000"
scale_type_y1 = "source"
scale_y1 = "1.000000"
shader2 = "shaders_slang/crt-hyllian-new-mask/shaders/crt-hyllian-base.slang"
filter_linear2 = "false"
wrap_mode2 = "clamp_to_border"
mipmap_input2 = "false"
alias2 = "CRTPass"
float_framebuffer2 = "true"
srgb_framebuffer2 = "false"
scale_type_x2 = "viewport"
scale_x2 = "1.000000"
scale_type_y2 = "viewport"
scale_y2 = "1.000000"
shader3 = "shaders_slang/crt-hyllian-new-mask/shaders/support/glow/threshold.slang"
filter_linear3 = "true"
wrap_mode3 = "clamp_to_border"
mipmap_input3 = "false"
alias3 = ""
float_framebuffer3 = "true"
srgb_framebuffer3 = "false"
shader4 = "shaders_slang/crt-hyllian-new-mask/shaders/support/glow/blur_horiz.slang"
filter_linear4 = "true"
wrap_mode4 = "clamp_to_border"
mipmap_input4 = "true"
alias4 = ""
float_framebuffer4 = "true"
srgb_framebuffer4 = "false"
scale_type_x4 = "viewport"
scale_x4 = "0.200000"
scale_type_y4 = "viewport"
scale_y4 = "1.000000"
shader5 = "shaders_slang/crt-hyllian-new-mask/shaders/support/glow/blur-glow-mask-geom.slang"
filter_linear5 = "true"
wrap_mode5 = "clamp_to_border"
mipmap_input5 = "false"
alias5 = ""
float_framebuffer5 = "true"
srgb_framebuffer5 = "false"
scale_type_x5 = "viewport"
scale_x5 = "1.000000"
scale_type_y5 = "viewport"
scale_y5 = "1.000000"
pf_console = "1.000000"
pf_contrast = "1.000000"
pf_color = "0.800000"
pf_connection = "1.000000"
pf_clipping = "2.000000"
pf_signalfringing = "1.000000"
pf_signalartifacting = "1.000000"
pf_videostd = "4.000000"
LUT_selector_param = "0.000000"
BEAM_MIN_WIDTH = "0.720000"
SCANLINES_STRENGTH = "0.860000"
MASK_STRENGTH = "1.000000"
BRIGHTBOOST = "1.000000"
GLOW_ENABLE = "0.000000"
textures = "SamplerLUT1;SamplerLUT2"
SamplerLUT1 = "shaders_slang/crt-hyllian-new-mask/shaders/support/LUT/Sony_Wega_29FA310_no_gamma-v2.png"
SamplerLUT1_wrap_mode = "clamp_to_border"
SamplerLUT1_mipmap = "false"
SamplerLUT2 = "shaders_slang/crt-hyllian-new-mask/shaders/support/LUT/Sony_Wega_29FA310_no_gamma.png"
SamplerLUT2_wrap_mode = "clamp_to_border"
SamplerLUT2_mipmap = "false"
2 Likes

I need to point out, the “red push” is not just some red color enhancer, but it’s the CRT’s way of approximating the NTSC standard from 1953 while compensating for using a bluer white than the standard. The default settings are calibrated against that, so that’s why you have to turn down saturation and adjust tint to make SNES games look anything like they’re supposed to, since those are often made for plain RGB. For NES, on the other hand, I would assume most games want standard NTSC settings.

Or maybe you’re from a PAL region, where (as far as I know for now) they fixed this problem a long time ago. In NTSC regions, SMPTE-170M only fixes this sometimes, but apparently CRT manufacturers never got the memo here. My Panasonic CRT from 2000 still has this “red push” over all 3 of its composite inputs, and the only bypass is YPbPr component.

I can say for sure that all settings in this are either 1. based on video standards, 2. based on my real CRTs, 3. based on real video decoder chips and their brand’s known phosphors, or 4. otherwise made as an educated guess. It’s accurate.

2 Likes

I just added in a simple hack to more easily darken over-saturated reds without needing to desaturate as much, in case that helps you. https://www.mediafire.com/file/u0c981wllep9a2q/patchy68k-1pass-2025-05-29-r2.zip/file

Also I see that you’re applying 2.4 gamma in this, but my shader already does gamma. You should change the gamma in my shader instead, unless you know what you’re doing.

I’ll do a fix soon to make it possible to skip gamma and/or NTSC color.

Edit: Here’s a version that can skip gamma and NTSC color. You can’t just set my shader’s gamma to 2.2; you have to enable “Skip all gamma correction”. To skip NTSC color, make sure you pick “Dummy” and not “SMPTE C”. https://www.mediafire.com/file/qlwkoqs77hdx1nb/patchy68k-1pass-2025-05-29-r3.zip/file I’ve realized that this shader does a poor job with double-resolution SNES games. I suggest prepending a SNES hi-res blending shader for now.

3 Likes

Thanks. I’m still learning how to integrate your shaders with others. That was a first approach. I know it has room for improvements. Thanks for the tips, I’ll test tomorrow that new version.

One thing I’d like to know about fringing: does it only manifests if you move the screen? I don’t remember very well if in real crt those artifacts change fase even if you pause the game.

2 Likes

The fringing artifacts are constantly there, but on most consoles, they are quickly flickering between two different offsets. Because of that, while holding still, artifacts visually cancel themselves out a little bit, and they become more jarring while moving.

For an example, I suggest looking up the cave in Battletoads on the NES. This particular NES game switches between 3 offsets instead of the usual 2, but it’s still a neat example of this effect. I know Game Grumps played it on original hardware at least once.

A few consoles, such as the Genesis/MegaDrive and Master System, have the phase constantly at one offset, so the artifacts don’t cancel themselves out while holding still.

Speaking of fringing, you should try adjusting the sharpness setting too. I’ve improved it over patchy-ntsc.

1 Like

2 Likes

The new params are great, thanks. One thing I noticed in the r3 version is that it offset the source someway and cut part of it horizontally.

1 Like

The version that I just uploaded fixes that and add a bunch of generic 2-phase and 1-phase options, but unfortunately, there’s a bit more performance overhead on this one. At least, I’m including a “speedup” version which slightly helps with that, but on that version, you have to manually fix the Color (Saturation) setting. The code is getting pretty messy and can use some optimization.

About that bug, it was a mistake with how the shader tries to automatically detect cropped/uncropped overscan and compensate for it. Notice how all the presets since r2 (or r3, I don’t remember) all have hardcoded absolute horizontal resolutions, unlike r1 which was a simple 2x multiplier. That way, you can set the horizontal resolution to whatever you want, and the shader will automatically either add pillarboxes or cut off the edges.

If you don’t want that behavior, you can instead change “absolute” to “source” and do 2.0x or 1.3333x, depending on which one you pick. (For the 2-phase or 3-phase ones, those multipliers are wrong. Instead, look at the “custom” settings at the bottom, and divide pixelSize by sampleSize to get the correct multiplier.)

Just be careful because the SNES can output either 256px or 512px, and making the resolution constantly 2x is going to cause 512px games to lag. The overscan compensation on top of that was just so that everything would stay in integer ratios for the shader to function right, but I guess it might also be a helpful feature for making presets, just maybe.

I’m curious, can anyone here from an NTSC region testify if they actually had this cursed brown Battletoads as a kid? (I’m pretty sure this doesn’t happen in PAL.)

I would guess many adjusted their TV’s tint setting to make it green, but if you did that, TV over the air would start looking messed up. For a lot of retro gaming, you might set your TV’s settings differently depending on whether you were playing video games or watching TV, and you wouldn’t know why it worked that way.

3 Likes

I don’t see anything wrong with the picture but I’m going on very old and unreliable memories.

What does the “uncursed” version look like for comparison?

2 Likes

Standard 1953 NTSC colorimetry: (This is closer to the CXA2025AS palette’s representation of this, unless you’re on Nestopia where they have their own CXA2025AS palettes)

Uncorrected: (This is more like FirebrandX’s palettes and Wavebeam)

I assume the second one is the intended result, since this game was developed in Europe by Rare.

Notice how even if you have the brown ground, there are strips of green in it

2 Likes

This wasn’t a thing at all.

Normal kids didn’t adjust their sets or tint for Retrogaming. We just played our games. There was no reference to tell us we weren’t seeing the right colours.

I know I used to adjust brightness to get better black levels though and I might have adjusted the colour to make things nice and vivid but I wouldn’t have known to adjust tint to get BattleToads colours corrected and definitely were not adjusting tint between gaming and regular TV watching.

Back then we used NTSC colour bars when TV signed off and eyeballing to get colours to look right.

A good reference might be a BattleToads review on Nintendo Power, E.G.M. or GamePro.

3 Likes

I thought this might be the case. This makes me glad that I’ve worked so hard over these months to figure out the decoder’s intended settings based on the broadcast standards. The default settings have the tint and color settings for broadcast, and the brightness for the game to become approximately 2.2 gamma.

The problem is with 16-bit onward, where some games become just obviously wrong, even if you have no reference for how it should look. That’s why my posts about “white trash” have those color test charts: You can’t tell if it’s calibrated/matched, but there are certain colors where you have a general idea of what they should look like and can tell if they’re messed up badly beyond a certain threshold. (I should also clarify, that post has the tint and color settings set to make the test chart results become as acceptably close as possible.)

The main question that’s unanswered for me is how you dealt with bright red at the time. Perhaps it’s not a problem for NES, but definitely elsewhere. On this old PR, I included a game that takes advantage of MegaDrive rainbow banding while also having oversaturated reds: https://github.com/libretro/slang-shaders/pull/627 Hyllian posted just a day ago that they don’t remember having red saturated that much, and the preset in that post has it down to 80%. Did you guys watch TV with 80% saturation on TVs that had an on-screen display?

About the games looking obviously wrong when your TV is set for standard NTSC, I’m wanting to share screenshots of that, but for some reason, everything suddenly just looks good for some reason. I could’ve sworn I saw some games getting screwed up badly when I tried these same color filters with Chthon’s color correction (particularly when using my reverse-engineered US 9300K color settings), but now that I’m trying again with my NTSC composite video filtering added on top of that, I’m having trouble finding games that look wrong. I thought for sure Moto Racer 2 looked absolutely horrible with standard NTSC color correction, but I’m starting to think now that the game is meant to have NTSC correction.

As I’ve said before, I grew up in the 2000s (in other words, Generation Z), so CRTs were only still around for a brief part of my life. I distinctly remember Crash Bandicoot being a deep red on those CRTs, not this lighter red that we see in emulation and the PS4 remakes, which points to the CRT not having been adjusted specifically for games. Still today, I generally play PS1 games with my CRT’s default settings (which are based on standard NTSC), or sometimes with color turned down a bit. NES and Genesis absolutely benefit from lower saturation on that CRT.

Can I just say, the PS4 Crash remakes are just… gross. All those goofy cartoonish death animations suddenly become like a realistic horror film, with some Baldi’s Basics style weirdness thrown in. I wanted to remember Crash Bandicoot, not KidPix Deluxe 4 Home Edition.

3 Likes

Even as a kid, I’ve always calibrated (by eye) my parent’s TVs to a neutral color position. And that worked for movies and games. If the set hadn’t the knob to adjust the tint, my only option was to desaturate all colors to some safe position.

4 Likes

Since we were discussing calibration, I’ve worked on this alternative multi-pass shader that more faithfully implements the NTSC video standard. The idea was to look up YouTube videos, watch them through the WindowCast core, and try my best to calibrate the tint and color dials by eye. The original video is converted into NTSC color, filtered with the standard filter characteristics before modulating, lowpassed under 4.2 MHz as if broadcast over air, demodulated with only narrowband filtering, and finally corrected back to sRGB in the same way a consumer CRT corrects NTSC color. All that’s missing right now is interlacing.

What I didn’t expect to come out of this was a substantial improvement in performance. What the heck just happened? https://www.mediafire.com/file/fdvi71hyi4bi3bs/p68k-fast-multipass-2025-06-12.zip/file SNES and mostly-standard 240p are supported well in the “multipass” subfolder, along with an incomplete NES implementation. If you’re looking for accuracy on NES, you should instead look inside the “presets” subfolder in this zip, and use the NES options in there, which have also been updated slightly.

I’m just very happy that this has unexpectedly happened. I’ll make a more serious, more complete post later.

P.S.: The way to disable gamma correction has changed. Simply change the CRT EOTF type from BT.1886 to the power law. These two things are default, but also make sure that the power is 2.2 and that the output sRGB EOTF is also a 2.2 power law. I’ve said before, but I suggest increasing sharpness a little, especially if using the 170m 240p preset which will have less artifacts.

P.P.S.: Some comments in the source code of the multipass shader are just blatantly wrong. There’s no need for the resolution to divide 2560 evenly, and there is no automatic letterboxing or cropping. Arbitrary cropped overscan compensation works completely different from that: It is now an optional feature which is handled similarly to Maister NTSC or NTSC Adaptive, with an added feature to detect if the resolution has been scaled by an arbitrary integer.

4 Likes