Old arcade games gamma curve

Some Mame games like contra, scontra, old irem such as ninja spirit, were made with strange gamma looking alright on old monitors but quite bad on modern LCD.

With Mame HLSL I could do a special ini to correct that.

Like for contra: offset -0.4,-0.4,-0.4 scale 1.4,1.4,1.4 power 0.8,0.8,0.8

Can’t really do the same with retroarch. I tried different shaders like bsnes-gamma-ramp.cg and image-adjustment.cg but they make the image dull or burn the high range if you push luminance a bit. As discussed in this thread it seems we need to apply a S curve.

Do we have a shader to do that?

I have no idea if this is the “correct” way to do it, but this seems to get pretty close to the fixed image from that thread (backing off the luminance to <1.0 might help with the hotspots a bit):

/* COMPATIBILITY 
   - HLSL compilers
   - Cg   compilers
*/

#define overscan float2(0.00, 0.00)
#define saturation 1.0
#define crt_gamma 2.4
#define monitor_gamma 2.2
#define luminance 1.0

struct input
{
  float2 video_size;
  float2 texture_size;
  float2 output_size;
  float  frame_count;
  float  frame_direction;
  float frame_rotation;
  sampler2D texture;
};

void main_vertex
(
	float4 position	: POSITION,
	float4 color	: COLOR,
	float2 texCoord : TEXCOORD0,

    uniform float4x4 modelViewProj,
	uniform input IN,

	out float4 oPosition : POSITION,
	out float4 oColor    : COLOR,
	out float2 otexCoord : TEXCOORD
)
{
	oPosition = mul(modelViewProj, position);
	oColor = color;
	float2 shift = 0.5 * IN.video_size / IN.texture_size;
	float2 overscan_coord = (texCoord - shift) * (1.0 - overscan) + shift;
	otexCoord = overscan_coord;
}

struct output 
{
  float4 color    : COLOR;
};

float3 grayscale(float3 col)
{
   return float3(dot(col, float3(0.2126, 0.7152, 0.0722)));
}

float4 main_fragment(float2 texCoord : TEXCOORD, uniform input IN) : COLOR
{
   float3 gamma = float3(crt_gamma / monitor_gamma);
   float3 res = tex2D(IN.texture, texCoord).xyz;
   res = lerp(grayscale(res), res, saturation); // Apply saturation
   res = (1.0 - cos(pow(res, gamma.rgb))) * 3.5; // Apply gamma curve
   return float4(saturate(res * luminance), 1.0);
}

I had the same result as you did using those shaders, which isn’t the best we can achieve. In fact we burn the lighter tones if we push luma above 1.2 while we can’t burn the darkest greys (which is what we want to do!).

There’s always some dark colors we shouldn’t see, guess they were burnt by the screens they were using in those cabinets at the time. Like this, in Ninja Spirits. (PC-Engine version on the right for comparison) Particularly this strange grey rectangle near the bridge. So Finally, in Retroarch I used crt-cgwg-geom with a 2.6 crt gamma and then tweaked in the Mame slider menu: brightness=“0.8” contrast=“1.2” gamma=“0.8”

For contra, scontra, most irem and sega16 games, I had a hard time. But it’s still the same, it’s possible with slider controls inside Mame. I’m using: brightness=“0.77” contrast=“1.45” gamma=“0.8”

Result is like this, this and this.

Now I need to find a way to make a cfg for all the games of a particular driver like in mame Standalone. :confused:

edit: So in conclusion I couldn’t do that with the shaders we have at the moment, but it works with mame options after all.

You can manipulate gamma and brightness without using a full on CRT shader. https://github.com/libretro/common-shad … ustment.cg

That’s not working well, I explained it above: image is dull or light tones turn all white with this shader. I want to keep a CRT shader, no problem here.