I've ported Guest-Dr-Venom to ReShade!

Any idea why the text is messed up? This pic is taken with the default settings in Guest-Dr-Venom. According to PC gaming wiki, the native resolution for Bloodstained is 426x240. I tried changing the Texture_Res_X in the .fx file to match, but it didn’t fix it. I also tried doubling the resolution, and that didn’t fix it either.

1 Like

Both axes are missing lines, so the res is too small in both directions. Perhaps it uses a different resolution in menus?

2 Likes

1st time here, and necroing this thread, but with the latest Reshade 5 update, i think it would be nice to see this added to shader repo

1 Like

NTSC-Adaptive for ReShade (with some help from @guest.r).

(Make sure Resolution X and Resolution Y are always the same size as NTSC_Adapt_X and NTSC_Adapt_Y respectively.)

Please report here if you find any bugs.

uniform float ResolutionX <
	ui_label = "Resolution X";
> = 320.0;

uniform float ResolutionY <
	ui_label = "Resolution Y";
> = 240.0;

uniform float quality <
	ui_type = "drag";
	ui_min = -1.0;
	ui_max = 2.0;
	ui_step = 1.0;
	ui_label = "NTSC Preset (SVideo=0 Composite=1 RF=2 Custom=-1)";
> = 1.0;

uniform float ntsc_fields <
	ui_type = "drag";
	ui_min = 0.0;
	ui_max = 1.0;
	ui_step = 1.0;
	ui_label = "NTSC Merge Fields";
> = 0.0;

uniform float ntsc_phase <
	ui_type = "drag";
	ui_min = 1.0;
	ui_max = 3.0;
	ui_step = 1.0;
	ui_label = "NTSC Phase: Auto | 2 Phase | 3 Phase";
> = 1.0;

uniform float ntsc_scale <
	ui_type = "drag";
	ui_min = 0.20;
	ui_max = 2.25;
	ui_step = 0.05;
	ui_label = "NTSC Resolution Scaling";
> = 1.0;

uniform float ntsc_sat <
	ui_type = "drag";
	ui_min = 0.0;
	ui_max = 2.0;
	ui_step = 0.01;
	ui_label = "NTSC Color Saturation";
> = 1.0;

uniform float ntsc_bright <
	ui_type = "drag";
	ui_min = 0.0;
	ui_max = 1.5;
	ui_step = 0.01;
	ui_label = "NTSC Brightness";
> = 1.0;

uniform float cust_artifacting <
	ui_type = "drag";
	ui_min = 0.0;
	ui_max = 5.0;
	ui_step = 0.1;
	ui_label = "NTSC Custom Artifacting Value";
> = 0.0;

uniform float cust_fringing <
	ui_type = "drag";
	ui_min = 0.0;
	ui_max = 5.0;
	ui_step = 0.1;
	ui_label = "NTSC Custom Fringing Value";
> = 0.0;

#include "ReShade.fxh"

#define TexSize float2(4.0*ResolutionX,ResolutionY)
#define IptSize float2(4.0*ResolutionX,ResolutionY)
#define SrcSize float4(TexSize,1.0/TexSize)
#define OptSize float4(IptSize,1.0/IptSize)
#define mix_mat float3x3(BRIGHTNESS,ARTIFACTING,ARTIFACTING,FRINGING,2.0*SATURATION,0.0,FRINGING,0.0,2.0*SATURATION)
#define rgb_mat float3x3(0.299,0.587,0.114,0.596,-0.274,-0.322,0.211,-0.523,0.312)
#define yiq_mat float3x3(1.000,0.956,0.621,1.000,-0.272,-0.647,1.000,-1.106,1.703)
#define tex_crd texcoord-float2(0.5/SrcSize.x,0.0)
#define fetch_offset(offset,one_x) tex2D(SamplerN,tex_crd+float2((offset)*(one_x),0.0)).xyz
#define fmod(x,y) (x-y*trunc(x/y))
#define PI 3.14159265

#ifndef NTSC_Adapt_X
#define NTSC_Adapt_X 320
#endif

#ifndef NTSC_Adapt_Y
#define NTSC_Adapt_Y 240
#endif

texture TextureN{Width=4.0*NTSC_Adapt_X;Height=NTSC_Adapt_Y;Format=RGBA16F;};
sampler SamplerN{Texture=TextureN;MinFilter=Point;MagFilter=Point;};

sampler Sampler0{Texture=ReShade::BackBufferTex;};

uniform int framecount<source="framecount";>;

float3 rgb2yiq(float3 rgb)
{
	return mul(rgb_mat, rgb);
}

float3 yiq2rgb(float3 yiq)
{
	return mul(yiq_mat, yiq);
}

float3 NTSC_1_PS(float4 position:SV_Position,float2 texcoord:TEXCOORD):SV_Target
{
	float pix_res = min(ntsc_scale, 1.0);
	float OrgSize = SrcSize.x / 4.0;
	float phase = (ntsc_phase < 1.5) ? ((OrgSize > 300.0) ? 2.0 : 3.0) : ((ntsc_phase > 2.5) ? 3.0 : 2.0);
	float res = ntsc_scale;

	float mod1 = 2.0;
	float mod2 = 3.0;

	float CHROMA_MOD_FREQ = (phase < 2.5) ? (4.0 * PI / 15.0) : (PI / 3.0);
	float ARTIFACTING = (quality > -0.5) ? quality : cust_artifacting;
	float SATURATION = ntsc_sat;
	float BRIGHTNESS = ntsc_bright;
	float FRINGING = (quality > -0.5) ? quality : cust_fringing;

	float MERGE;

	MERGE = (int(quality) ==  2 || phase < 2.5) ? 0.0 : 1.0;
	MERGE = (int(quality) == -1) ? ntsc_fields : MERGE;

	float2 pix_no = texcoord * SrcSize.xy * (pix_res * OptSize.xy / SrcSize.xy);

	float3 col = tex2D(Sampler0, texcoord).rgb;

	float3 yiq1 = rgb2yiq(col);
	float3 yiq2 = yiq1;	
	float3 yiqs = yiq1;
	float3 yiqz = yiq1;

if (MERGE > 0.5)
{
	float chroma_phase2 = (phase < 2.5) ? PI * (fmod(pix_no.y, mod1) + fmod(framecount+1, 2.)) : 0.6667 * PI * (fmod(pix_no.y, mod2) + fmod(framecount+1, 2.));
	float mod_phase2 = chroma_phase2 + pix_no.x * CHROMA_MOD_FREQ;

	float i_mod2 = cos(mod_phase2);
	float q_mod2 = sin(mod_phase2);

	yiq2.yz *= float2(i_mod2, q_mod2);
	yiq2 = mul(mix_mat, yiq2);
	yiq2.yz *= float2(i_mod2, q_mod2);

if (res > 1.025)
{
	mod_phase2 = chroma_phase2 + pix_no.x * CHROMA_MOD_FREQ * res;

	i_mod2 = cos(mod_phase2);
	q_mod2 = sin(mod_phase2);

	yiqs.yz *= float2(i_mod2, q_mod2);
	yiq2.x = dot(yiqs, mix_mat[0]);
}
}

	float chroma_phase1 = (phase < 2.5) ? PI * (fmod(pix_no.y, mod1) + fmod(framecount, 2.)) : 0.6667 * PI * (fmod(pix_no.y, mod2) + fmod(framecount, 2.));
	float mod_phase1 = chroma_phase1 + pix_no.x * CHROMA_MOD_FREQ;

	float i_mod1 = cos(mod_phase1);
	float q_mod1 = sin(mod_phase1);

	yiq1.yz *= float2(i_mod1, q_mod1);
	yiq1 = mul(mix_mat, yiq1);
	yiq1.yz *= float2(i_mod1, q_mod1);

if (res > 1.025)
{
	mod_phase1 = chroma_phase1 + pix_no.x * CHROMA_MOD_FREQ * res;

	i_mod1 = cos(mod_phase1);
	q_mod1 = sin(mod_phase1);

	yiqz.yz *= float2(i_mod1, q_mod1);
	yiq1.x = dot(yiqz, mix_mat[0]);
}

	yiq1 = (MERGE < 0.5) ? yiq1 : 0.5*(yiq1+yiq2);

	return float4(yiq1, 1.0);
}

float3 NTSC_2_PS(float4 position:SV_Position,float2 texcoord:TEXCOORD):SV_Target
{
	const float chroma_filter_2_phase[33] = {
    0.001384762, 0.001678312, 0.002021715, 0.002420562, 0.002880460, 0.003406879, 0.004004985, 0.004679445, 0.005434218, 0.006272332, 0.007195654,
    0.008204665, 0.009298238, 0.010473450, 0.011725413, 0.013047155, 0.014429548, 0.015861306, 0.017329037, 0.018817382, 0.020309220, 0.021785952,
    0.023227857, 0.024614500, 0.025925203, 0.027139546, 0.028237893, 0.029201910, 0.030015081, 0.030663170, 0.031134640, 0.031420995, 0.031517031};

	const float chroma_filter_3_phase[25] = {
   -0.000118847,-0.000271306,-0.000502642,-0.000930833,-0.001451013,
   -0.002064744,-0.002700432,-0.003241276,-0.003524948,-0.003350284,
   -0.002491729,-0.000721149, 0.002164659, 0.006313635, 0.011789103,
    0.018545660, 0.026414396, 0.035100710, 0.044196567, 0.053207202,
    0.061590275, 0.068803602, 0.074356193, 0.077856564, 0.079052396};

	const float luma_filter_2_phase[33] = {
   -0.000174844,-0.000205844,-0.000149453,-0.000051693, 0.000000000,-0.000066171,-0.000245058,-0.000432928,-0.000472644,-0.000252236, 0.000198929,
    0.000687058, 0.000944112, 0.000803467, 0.000363199, 0.000013422, 0.000253402, 0.001339461, 0.002932972, 0.003983485, 0.003026683,-0.001102056,
   -0.008373026,-0.016897700,-0.022914480,-0.021642347,-0.008863273, 0.017271957, 0.054921920, 0.098342579, 0.139044281, 0.168055832, 0.178571429};

	const float luma_filter_3_phase[25] = {
   -0.000012020,-0.000022146,-0.000013155,-0.000012020,-0.000049979,
   -0.000113940,-0.000122150,-0.000005612, 0.000170516, 0.000237199,
    0.000169640, 0.000285688, 0.000984574, 0.002018683, 0.002002275,
   -0.000909882,-0.007049081,-0.013222860,-0.012606931, 0.002460860,
    0.035868225, 0.084016453, 0.135563500, 0.175261268, 0.190176552};

	const int TAPS_2_phase = 32;

	const int TAPS_3_phase = 24;

	float OrgSize = SrcSize.x / 4.0;
	float phase = (ntsc_phase < 1.5) ? ((OrgSize > 300.0) ? 2.0 : 3.0) : ((ntsc_phase > 2.5) ? 3.0 : 2.0);
	float res = ntsc_scale;
	float one = SrcSize.z / res;

	float3 signal;

if (phase < 2.5)
{
	for (int i = 0; i < TAPS_2_phase; i++)
	{
	float offset = float(i);

	float3 sums = fetch_offset(offset - float(TAPS_2_phase), one) + fetch_offset(float(TAPS_2_phase) - offset, one);

	signal += sums * float3(luma_filter_2_phase[i], chroma_filter_2_phase[i], chroma_filter_2_phase[i]);
	}

	signal += tex2D(SamplerN, tex_crd).xyz * float3(luma_filter_2_phase[TAPS_2_phase], chroma_filter_2_phase[TAPS_2_phase], chroma_filter_2_phase[TAPS_2_phase]);}else

if (phase > 2.5)
{
	for (int i = 0; i < TAPS_3_phase; i++)
	{
	float offset = float(i);

	float3 sums = fetch_offset(offset - float(TAPS_3_phase), one) + fetch_offset(float(TAPS_3_phase) - offset, one);

	signal += sums * float3(luma_filter_3_phase[i], chroma_filter_3_phase[i], chroma_filter_3_phase[i]);
	}

	signal += tex2D(SamplerN, tex_crd).xyz * float3(luma_filter_3_phase[TAPS_3_phase], chroma_filter_3_phase[TAPS_3_phase], chroma_filter_3_phase[TAPS_3_phase]);}

	float3 rgb = yiq2rgb(signal);

	return float4(rgb, 1.0);
}

technique NTSC_Adaptive
{
pass NTSC_Pass_1
{
VertexShader=PostProcessVS;
PixelShader=NTSC_1_PS;
RenderTarget=TextureN;
}
pass NTSC_Pass_2
{
VertexShader=PostProcessVS;
PixelShader=NTSC_2_PS;
}
}

Some shots with CRT-Geom on top :

8 Likes

Hi, I realized that the latest version of the CRT-Guest-Advanced port is not in the first post, can you point me in the direction of the latest version please?

Also, can you give me a quick description of the installation steps for your shaders please?

I’ve used ReShade before but only installed it a few times so I might just need a quick refresher.

I would like to create my own preset for TMNT: Shredder’s Revenge. Haven’t found the native resolution on PC Gaming Wiki.

I’m going to start winging it but any assistance would be greatly appreciated.

1 Like

That’s the most latest (over a year old) version of GDV-Advanced ReShade port. Just copy and save it as a .fx text file.

(I’ll be able to help you more in the morning as I’m currently preparing to go to sleep.)

1 Like

Thanks, I got it installed. The next issue is that the resolution looks too low and I can’t seem to increase it from 320 x 240. I tried CRT-Geom and I was able to change the resolution to 720 x 360 and the scanlines look a bit even now.

I’m looking forward to learning how to use ReShade as well as I use can native RetroArch CRT Shaders.

Update: 480 x 270 Seems to work well.

You have to click on the image then click Load Full Resolution, Then zoom in or view Fullscreen.

Update:

I think I’ve got it.

CyberLab ReShade Death To Pixels Shader Preset Pack 19-06-22.zip

Examples:

2 Likes

Yes. 270 height seems to be the correct height for this game. The easiest way to figure out the internal resolution of these modern pixel art games is to look at the DIAGONAL lines in the image when using a scanline shader. If they look right/clean, you have found the right resolution.

GDV-Advanced (960x270) :

Raw :

5 Likes

Is there a tutorial on how to convert a Retroarch shader to Reshade? There are a bunch of old PC games in 4:3 I’d like the option to use ambient glow on them.

Is there a way to stagger the mask to turn the aperture grill mask into a shadow mask like in the libretro version?