{"id":28386581,"url":"https://github.com/blitzcode/crt-240p-scale-shader","last_synced_at":"2025-06-26T15:31:21.034Z","repository":{"id":54842874,"uuid":"342622576","full_name":"blitzcode/crt-240p-scale-shader","owner":"blitzcode","description":"RetroArch GLSL shader for 240p CRT output","archived":false,"fork":false,"pushed_at":"2021-05-13T17:08:21.000Z","size":1130,"stargazers_count":20,"open_issues_count":0,"forks_count":1,"subscribers_count":3,"default_branch":"main","last_synced_at":"2025-05-30T19:17:56.427Z","etag":null,"topics":["crt-monitor","glsl","raspberry-pi","raspberry-pi-3","retrogaming","retropie","shaders"],"latest_commit_sha":null,"homepage":"","language":"GLSL","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/blitzcode.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2021-02-26T15:46:02.000Z","updated_at":"2025-05-25T22:36:31.000Z","dependencies_parsed_at":"2022-08-14T04:31:02.247Z","dependency_job_id":null,"html_url":"https://github.com/blitzcode/crt-240p-scale-shader","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/blitzcode/crt-240p-scale-shader","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/blitzcode%2Fcrt-240p-scale-shader","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/blitzcode%2Fcrt-240p-scale-shader/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/blitzcode%2Fcrt-240p-scale-shader/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/blitzcode%2Fcrt-240p-scale-shader/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/blitzcode","download_url":"https://codeload.github.com/blitzcode/crt-240p-scale-shader/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/blitzcode%2Fcrt-240p-scale-shader/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":262094335,"owners_count":23257934,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["crt-monitor","glsl","raspberry-pi","raspberry-pi-3","retrogaming","retropie","shaders"],"created_at":"2025-05-30T15:11:39.635Z","updated_at":"2025-06-26T15:31:21.024Z","avatar_url":"https://github.com/blitzcode.png","language":"GLSL","funding_links":[],"categories":[],"sub_categories":[],"readme":"\n# CRT 240p Scale Shader\n\n![Hero](doc-img/hero.png?raw=true)\n\n## What's this?\n\nThis is a [RetroArch](https://www.retroarch.com/)\n[GLSL](https://en.wikipedia.org/wiki/OpenGL_Shading_Language) shader for scaling a wide\nrange of emulated consoles, handhelds and arcade systems to look high-quality and\nauthentic on a standard definition, horizontal, 4:3, CRT TV through a single 240p super\nresolution.\n\nI'm using the shader with a customized [RetroPie](https://retropie.org.uk/) installation on a\n[Raspberry Pi](https://www.raspberrypi.org/) 3B with a\n[PI2SCART](http://arcadeforge.net/Pi2Jamma-Pi2SCART/PI2SCART::264.html) hat, but it should\nwork fine with different 240p RGB output solutions or software setups.\n\nWhile I cannot claim the results to be absolutely perfect, it has certainly satisfied me,\nsomebody deeply familiar with how most of the systems in RetroPie look as original hardware on\na CRT or through an OSSC. I went from constantly tweaking my RetroArch scaling\noptions to simply playing games.\n\n## Features\n\n![Super](doc-img/super.jpg?raw=true)\n\n- Supports a wide range of emulators with no need for per-system or per-game tweaking. Set\nthis up once and play thousands of games without ever thinking about aspect ratios,\nresolutions, scaling, centering, shimmering, interpolation, etc. again\n- Care is taken to have the authentic looking aspect ratio for all systems\n- Never introduce blurring through filtering on the horizontal axis and filtering is never\nvisible vertically unless downscaling is required\n- TATE games will be automatically displayed in the correct orientation and aspect ratio.\nSuper-sampling is employed to reduce vertical shimmering and a gentle sharpening filter\nmitigates the loss of vertical resolution. An optional overscan correction can be applied\nas TATE arcade games are generally not designed with consumer CRT overscan in mind\n- Displays handhelds with the correct aspect ratio and by centering them on-screen. TATE\nhandhelds like the WonderSwan and Lynx are supported, including mid-game rotation\n- Code is very short, well-documented and simple. It's trivial to add special cases\nfor a specific resolution or system\n- Negligible performance impact\n\n## Motivation\n\n![Clarkson](doc-img/clarkson.jpg?raw=true)\n\nIf you've ever tried to get a number of RetroArch cores emulating dozens of consoles,\nhandhelds and arcade systems to look correct on your CRT, you don't need to read this.\nYou know what a glitchy mess the Settings-\u003eVideo-\u003eScaling menu is and how ill-equipped\nRetroArch scaling is to deal with things like non-square pixel super wide resolutions.\nBut if you need a reason why this shader exists, let's see what you'd have to do\nwithout it.\n\nWe want want to use a standard definition 4:3 CRT and have configured our system to output\nat a reasonable 320x240 resolution. We'll now go through a few typical game resolutions\nand see what we have to do to convince RA to output in a matter that looks authentic and\nhigh quality.\n\n- **320x240** -\nNothing to be done, great!\n- **320x224** -\nThe wrong thing would be to stretch 224 lines to 240. This would give both the wrong\naspect ratio and introduce severe blurring. We can achieve the correct vertical centering\nof 224 lines inside 240 with integer scaling, but the image would then not use the full 320\nhorizontal pixels in each line as the aspect ratio math is done incorrectly on 224 lines.\nEven for this simple case already we'd have to use the 'custom' mode and configure the\nscaling completely manually\n- **320x256** -\nArcade games like R-Type often output in \u003e240p resolutions, we need to downscale.\nUnfortunately, RA does not support this very well as the input is not MIP-mapped and\nthere's no build-in supersampling, so shimmering is unavoidable. The best we can do is\nturn on bilinear filtering in the video menu. This can only be done for both axis at the\nsame time and can introduce a loss of sharpness and brightness in small features on an\naxis where it isn't even required.\n- **160x144** -\nHandheld resolutions like these can only be properly displayed by centering them\non-screen. One complication is that some handhelds do not have square pixels. Time to\npull out the calculator to find the correct image width and on-screen X/Y offsets.\n- **256x224** -\nThere is no way to make this horizontal resolution look good with our chosen output\nresolution. We can either assume square pixels and a 8:7 aspect, which would look sharp but\nwrong with a squeezed image and black borders or we can stretch 256 to 320 and introduce\nsevere blurring. At this point we'd have no choice but to detect the system in the\n`runcommand-onstart.sh` script and chose a different output resolution for each console.\n- **352x240** -\nMany consoles like the PC Engine or the PS1 have a wide range of output resolutions and\nthere is no one resolution correct for the entire library. We need a per-game resolution\ndatabase to handle all those systems correctly. But even this doesn't work in all cases as\nsome games switch resolution mid-game or let the user chose the output resolution (Soldier\nBlade on PCE, for instance). The only thing we can do now is to use a CRT super resolution.\n\n_CRT Super Resolution?_\n\nThe idea behind resolutions like 1920x240 is that it allows quality scaling for a range of\nhorizontal resolutions used by different systems. Vertical resolution mismatches like 224\nor 192 lines in a 240 output are resolved by centering, but horizontal resolution\nmismatches have to be resolved by stretching / scaling. Stretching 256 to 320 pixels will\nalways look bad, but 352/320/256 pixels can be quite easily stretched to 1920 or 2048\npixels with minimal scaling artifacts, invisible on a typical consumer CRT display. Since\nCRTs do not have a fixed horizontal resolution or any hard upper limit it is possible to\ndrive even standard definition TVs with 1920, 2048, 3840 etc. horizontal pixels.\n\nUnfortunately, this means our output display will have a non-square pixel aspect ratio,\nsomething RA is not specifically equipped to handle. We'll need to use the 'custom'\nscaling mode and do all of the aspect ratio and centering computation ourselves.\n- **240x320** -\nThis is typical for TATE / vertical arcade games. If we want these to display properly\nwe'll first have to downsize them as nicely as possible (not something RA supports\n    natively, as discussed earlier) and then we'll have to center and stretch them to\nmaintain their correct aspect ratio. All this is further complicated by the non-square\npixel aspect ratio of our super resolution. To do this with RA's default scaling pipeline\nwe'd need a database of which games are TATE, their resolution and then do the math and\ncustom per-game setup in the `runcommand-onstart.sh` script. Or manually create a custom\nper-game configuration for each game.\n- **224x144 / 144x224** -\nEven if we're willing to do all the manual or script development work above all of this\nfinally breaks down with systems like the WonderSwan which can be used both horizontally\nand vertically and has some games that even switch the handheld orientation mid-game.\n\n![Mind Blown](doc-img/mind-blown.gif?raw=true)\n\n_A typical user trying to figure out the correct width of the image of a 3:4 game\nrunning on a 4:3 TV with a 6:1 pixel aspect ratio_\n\nAt this point it should be abundantly clear how tedious and complicated configuring\nall of this manually is. Thankfully, this shader handles all of the above without any\nmanual tweaking required or you ever having to get out the calculator to figure out the\ncorrect settings.\n\n## Setup\n\n![Raspberry Pi](doc-img/raspberry-pi.jpg?raw=true)\n\nThese are the setup instructions for RetroPie 4.7.1 running on a series 3 Raspberry Pi.\n\nFirst, we have to setup super resolution output for all emulators. Since EmulationStation\ncan't deal with these we want to use a standard square pixel resolution for it and only\nswitch to our super resolution for the actual emulators.\n\nA good place to do so are the onstart / onend scripts. \n\n\n`/opt/retropie/configs/all/runcommand-onstart.sh`:\n\n```\nvcgencmd hdmi_timings 1920 1 79  208 241 240 1 6 10 6 0 0 0 60 0 38400000 1 \u003e /dev/null\ntvservice -e \"DMT 87\" \u003e /dev/null\nfbset -depth 8 \u0026\u0026 fbset -depth 16 -xres 1920 -yres 240 \u003e /dev/null\n```\n\n`/opt/retropie/configs/all/runcommand-onend.sh`:\n\n```\nvcgencmd hdmi_timings 320 1 11 30 38 240 1 8 3 16 0 0 0 60 0 6400000 1 \u003e /dev/null\ntvservice -e \"DMT 87\" \u003e /dev/null\nfbset -depth 8 \u0026\u0026 fbset -depth 16 -xres 320 -yres 240 \u003e /dev/null\n```\n\nYou'll have to adjust your TV's service menu and / or the [display\ntimings](https://www.reddit.com/user/ErantyInt/comments/g3c98h/crtpiproject_presents_adjusting_hv_position_with/)\nused here to center and size the image correctly.\n\nNext we have to configure RetroArch scaling. Specifically, we want RA to do as little as\npossible, fill out the entire screen and not filter anything. We want all the work to\nbe done by the shader. Here are settings that can be written to the global RA configuration.\n\n`/opt/retropie/configs/all/retroarch.cfg`:\n\n```\naspect_ratio_index = \"23\"\ncustom_viewport_width = \"1920\"\ncustom_viewport_height = \"240\"\ncustom_viewport_x = \"0\"\ncustom_viewport_y = \"0\"\nvideo_smooth = \"false\"\nvideo_scale_integer = \"false\"\n```\n\nYou can of course also do that manually in the RGUI Settings-\u003eVideo-\u003e... menus by setting\nthe aspect ratio to 'Custom', dialing in your chosen super resolution and disabling\ninteger scaling and bilinear filtering.\n\nBy default RGUI doesn't cope well with our super resolution, but we can add\n`rgui_aspect_ratio_lock = \"3\"` or manually change\nSettings-\u003eUser Interface-\u003eAppearance-\u003eLock Menu Aspect Ratio-\u003eStretch to fix this.\n\nKeep in mind that any per-system settings, core or game overrides might overwrite the\nglobal settings. Please read\n[this guide](https://retropie.org.uk/forum/topic/22816/guide-retroarch-system-emulator-core-and-rom-config-files)\nif you're confused about how to get your settings used everywhere.\n\nNow all that is left is to configure RA to use the shader. Clone the repository on your\nPi and use RGUI to load the shader with Quick Menu-\u003eShaders-\u003eLoad Shader Preset.\nFinally, save it as a preset to be used by all systems with Save-\u003eSave Global Preset\nfrom the same menu.\n\nThat's it, now nearly all your games should display properly without any further tweaking.\n\n## More Setup\n\n![RetroPie](doc-img/retropie.png?raw=true)\n\nIf you need help setting up your RetroPie CRT system in general, please see my extensive\n[notes](https://github.com/blitzcode/retropie-setup-notes/blob/master/notes.txt).\n\nThey cover not only CRT and scaling specific issues but also more general things like\ninput lag, overclocking, USB sound cards, turbo fire, BIOS files, backups, etc.\n\n## TODO / Limitations\n\n- Game Gear has the wrong aspect ratio as we cannot distinguish it from the GB(C) by the\nresolution alone\n- There are going to be some unusual arcade games that have resolutions or screen setups\nthat are not properly handled by this shader (...but adding special case support is\nstraightforward)\n- Using a single resolution will never correctly accommodate arcade games running at\nwildly varying refresh rates and scaling on the horizontal axis will not be pixel-perfect\nfor most systems (not that big of a deal on a typical consumer CRT TV driven at a super\nresolution)\n- Vertical downscaling could probably use something better than the simple tent +\nsharpening combination\n- Very low-resolution systems like the Lynx could be pixel doubled and still fit into 240p\n\n## Code\n\nYou are encouraged to have a look at the [shader](crt-240p-scale-shader.glsl) source code. It\nhas less than 100 lines of actual code and is well-documented and easy to understand.\nCustomizing it should be very simple.\n\n## Special Thanks\n\nI didn't end up using either of these in my personal setup, but both the\n[CRTPi Project](https://www.reddit.com/user/ErantyInt/comments/gqz3qo/crtpiproject_project_image_megathread/)\nand\n[Snap-Shader](https://github.com/ektgit/snap-shader-240p)\nwere hugely helpful when figuring out how build my own custom setup. \n\n## Legal\n\nThis program is published under the [MIT License](http://en.wikipedia.org/wiki/MIT_License).\n\n## Author\n\nDeveloped by Tim C. Schroeder, visit my [website](http://www.blitzcode.net) to learn more.\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fblitzcode%2Fcrt-240p-scale-shader","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fblitzcode%2Fcrt-240p-scale-shader","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fblitzcode%2Fcrt-240p-scale-shader/lists"}