Download
Installation
Copy the scripts above Main as usual, first Zeus Module.rb then Fullscreen++.rb.
Copy Fullscreen.dll into the game folder or into its System subfolder.
If your game is released on Steam you can also copy steam_api.dll.
This allows better integration by pausing the game while the Steam overlay is displayed.
You can also set the app ID at the beginning of the script to activate Steam’s DRM.
Keyboard Shortcuts
F11 : toggle fullscreen
Shift + F11 : switch aspects (stretch - keep ratio - integer)
Ctrl + F11 : switch shaders
Configuration
To be placed in the Game.ini:
Code:
[Fullscreen++]
Fullscreen=true
VSync=true
BlackFrame=false
KeepAspect=1
Overscan=0.0
BackEffect=Blur()
BackAspect=2
EffectId=2
Effect0=RAA() SimpleScale()
Effect1=MMPX() SimpleScale()
Effect2=ScaleFX() SimpleScale()
Effect3=FSR() SimpleScale()Fullscreen = true or false : enable fullscreen at game start.
VSync = true or false : enable/disable vertical sync to prevent screen tearing.
BlackFrame = true or false : enable/disable BFI mode, reduces motion blur.
KeepAspect = 0, 1, or 2 : stretch, keep ratio, or integer scaling.
Overscan = -0.5 à +0.5 : zoom in/out inside the game window.
BackEffect = string : defines the background when the game image doesn’t fill the window.
- If string is empty : black background.
- If string is a filename : displays an image from Graphics/Pictures or the game folder.
- If string is Blur() : shows a blurred version of the game image, with optional parameters that I will describe after.
BackAspect = x : defines how the background image is displayed.
- 0 : stretch to full window (interpolation depends on last SimpleScale settings).
- 1 : keeping aspect ratio (fit in), uncovered areas are black.
- 2 : keeping aspect ratio (fit out).
- 3 : center without scaling, uncovered areas are black.
- 4 : tile the image without scaling.
EffectId = x : id of the active effect.
EffectN = shaders : list of shaders applied in order, the last must be SimpleScale.
At least one effect must be defined (Effect0). There is no max limit, but cycling through 1000 effects with Ctrl+F11 would be painful,
so better keep it reasonable.
Script Commands
Graphics.fullscreen = true or false
Graphics.vsync = true or false
Graphics.black_frame = true or false
Graphics.keep_aspect = 0, 1, or 2
Graphics.overscan = -0.5 à +0.5
Graphics.background[0] = "BackEffect"
Graphics.background[1] = BackAspect
Graphics.effect_id = x
Graphics.effects = ["Effect0", ...]
Graphics.load_settings(filename) : optional filename, defaults to Game.ini
Graphics.save_settings(filename) : optional filename, defaults to Game.ini
Shaders
The formatting must be: ShaderName(option1:x, option2:y, option3:z)
Parameter order can’t be changed, but parameter names may be omitted: ShaderName(x, y, z)
All parameters must be present or may be omitted entirely: ShaderName()
Therefore it will use default parameters which are listed below.
SimpleScale(scale:0, interpolation:1)
scale: > 0 = fixed value, 0 = auto fit to window, -1 = auto integer scale, -2 = auto power of 2, -3 = auto power of 3
interpolation: 0 = none (nearest neighbor), 1 = bilinear, 2 = bicubic

A SimpleScale must also be used as the final shader, the scale value will be ignored and set to 0.
The interpolation value of the final SimpleScale will also be used for the background image if there is one.
But nothing prevents you from using the shader multiple times, for example to do what’s called sharp bilinear: SimpleScale(-1, 0) SimpleScale(0, 1)
CAS(scale:0, sharpness:0.9, preset:0)
scale: > 0 = fixed value, 0 = auto fit to window, -1 = auto integer scale, -2 = auto power of 2, -3 = auto power of 3
sharpness: 0.0 = off, 1.0 = max
preset: 0 = fast, 1 = balanced, 2 = slow


CAS = Contrast Adaptative Sharpening, it can upscale, but it can also be used as a simple sharpening filter by setting scale to 1.
FSR(scale:0, sharpness:0.9)
scale: > 0 = fixed value, 0 = auto fit to window, -1 = auto integer scale, -2 = auto power of 2, -3 = auto power of 3
sharpness: 0.0 = off, 1.0 = max


FSR = FideltyFX Super Resolution, unlike CAS, it's not recommended to use FSR with scale set to 1, it's not designed for that.
RAA(scale:0, interpolation:1, sharpness:1.0)
scale: > 0 = fixed value, 0 = auto fit to window, -1 = auto integer scale, -2 = auto power of 2, -3 = auto power of 3
interpolation: 0 = none (nearest neighbor), 1 = bilinear, 2 = bicubic
sharpness: 0.0 = off, 1.0 = max

RAA = Reverse Anti Aliasing, as the name may (not) imply, it's very effective at upscaling already smoothed elements such as texts.
It tends to leave pixel art mostly intact (though if you zoom in you’ll see it still affects it slightly).
This filter only upscales by integer values, if the target scale is not an integer, an additional SimpleScale shader will be applied to reach the final size using the chosen interpolation.
MMPX(scale:0, interpolation:1, threshold:0.2, RAA_Sharpness:0.0)
scale: > 0 = fixed value, 0 = auto fit to window, -1 = auto integer scale, -2 = auto power of 2, -3 = auto power of 3
interpolation: 0 = none (nearest neighbor), 1 = bilinear, 2 = bicubic
threshold: 0.0 = off, 1.0 = max, allows tolerance in color comparisons.
RAA_Sharpness: 0.0 = off, 1.0 = max, useful when your game mixes pixel art and smooth images, it applies RAA to non–pixel-art elements.


MMPX is a filter specialized in pixel-art upscaling with the goal of preserving the original style.
Because of that, it's extremely sensitive to even the smallest color variations, heavy fog or transparency effects will break it.
This filter only upscales by x2, if the upscale value is greater than 2, the filter will be applied repeatedly until the target scale is reached,
and if it is not a power of 2, an additional SimpleScale shader is applied using the chosen interpolation.
ScaleFX(scale:0, interpolation:1, filterAA:false, filterCorners:true, threshold:0.5, RAA_Sharpness:0.0)
scale: > 0 = fixed value, 0 = auto fit to window, -1 = auto integer scale, -2 = auto power of 2, -3 = auto power of 3
interpolation: 0 = none (nearest neighbor), 1 = bilinear, 2 = bicubic
filterAA: true or false, allows ScaleFX to process AA elements, not as good as RAA but preserves pixel art better (avoid enabling both).
filterCorners: true or false, ScaleFX tends to round corners, disable this to keep perfectly square corners (may false detect some corners though).
threshold: 0.0 = off, 1.0 = max, tolerance in color comparisons.
RAA_Sharpness: 0.0 = off, 1.0 = max, useful when your game mixes pixel art and smooth images, it applies RAA to non–pixel-art elements.


ScaleFX is the Rolls Royce of pixel-art upscalers with advanced handling of curves and oblique lines, where other upscalers create jaggies.
This filter only upscales by x3, if the upscale value is greater than 3, the filter will be applied repeatedly until the target scale is reached,
and if it is not a power of 3, an additional SimpleScale shader is applied using the chosen interpolation.
SMAA(preset:3, colorEdgeDetection:true, localContrastAdapt:2.0, threshold:0.8)
preset: 0 = low, 1 = medium, 2 = high, 3 = ultra
colorEdgeDetection: true ou false, SMAA has two edge detection modes, luminance-based or color-based, color-based is better.
localContrastAdapt: x > 1, ignores edges with contrast above x.
threshold: 0.0 = off, 1.0 = max, avoids smoothing edges that are already smooth.

SMAA = Subpixel Morphological Anti-Aliasing, the best post-processing AA.
Like MMPX, it is sensitive to color variations and can shimmer easily.
Blur(mode:0, quality:5, radius:1.0, angle:0.0, centerX:0.5, centerY:0.5, downscale:0)
mode: 0 = regular blur, 1 = linear blur, 2 = spin blur, 3 = zoom blur, 4 = spiral blur
quality: 1 = min, 9 = max, number of passes, higher = better but heavier.
radius: 0.0 = min, 100.0 = max, higher radius requires higher quality to remain smooth.
angle: x, angle for linear blur, for spin/zoom/spiral blurs indicates direction: -1 = counterclockwise/unzoom, 0 = bidirectional, +1 = clockwise/zoom.
centerX, centerY: x, coordinates of the blur origin (percentage).
downscale: 0 = auto, > 1 = fixed value, downscales the image before blurring for better performance.
The direct use of this shader is limited, maybe for transitions?
It's mainly used by the Glow shader and for window background effects.
Glow(blendMode:8, blendOpacity,:1.0 lumaThreshold:0.0, thresholdSoftness:0.0, intensityR:0.5, intensityG:0.5, intensityB:0.5, blurMode:0, blurQuality:5, blurRadius:1.0, blurAngle:0.0, blurCenterX:0.5, blurCenterY:0.5)
blendMode: 0 = normal linear , 1 = normal srgb,
2 = multiply linear , 3 = multiply srgb,
4 = hard light linear, 5 = hard light srgb,
6 = overlay linear , 7 = overlay srgb,
8 = soft light linear , 9 = soft light srgb,
10 = screen linear , 11 = screen srgb,
12 = add linear , 13 = add srgb
blendOpacity: 0.0 = off, 10.0 = max, values can go above 100% (1.0) to increase the effect further.
lumaThreshold: 0.0 = off, 1.0 = max, applies the filter only to pixels whose brightness exceeds the threshold.
thresholdSoftness: 0.0 = off, 1.0 = max, -1.0 = max inverted, softens the on/off transition of the brightness mask, negative values invert the mask.
intensityR, intensityG, intensityB: x < 1 = reduces color intensity, x > 1 = increase color intensity.
blurMode, blurQuality, blurRadius, blurAngle, blurCenterX, blurCenterY: same as Blur shader.
Palette(paletteId:1, smooth:false, ditherMode:1, ditherAnime:0, ditherAmount:0, sharpness:0.4, customColors:[])
paletteId: 0 = Black & White, 1 = GB DMG, 2 = GB Light, 3 = Virtual Boy, 4 = LCD, 5 = Sepia, 6 = Pastel, 7 = Burning Sunset, 8 = Midnight Purple,
9 = Inverted Matrix, 10 = CGA 1, 11 = CGA 2, 12 = Cocorico, 13 = Custom Colors, 14 = Macintosh, 15 = NES, 16 = 8 Bit Depth
smooth: true or false, adds intermediate colors to the palette.
ditherMode: 0 = off, 1 = Bayer Matrix 2x2, 2 = Bayer Matrix 4x4, 3 = Bayer Matrix 8x8, 4 = Bayer Matrix 16x16, 5 = Blue Noise (Gray), 6 = Blue Noise (RGB )
ditherAnime: 0 = off, x = dithering animation frequency, every x frames.
ditherAmount: 0.0 = auto, 1.0 = max
sharpness: 0.0 = off, 10.0 = max, coarse sharpening filter that adds ringing but can help low-color palettes (creates outlines).
customColors: [#RRGGBB, #RRGGBB, #RRGGBB, #RRGGBB], defines 4 hex colors for palette 13.
Daltonize(anomaly:0, severity:1.0)
anomaly: 0 = Protanopia Simulation , 1 = Deuteranopia Simulation , 2 = Tritanopia Simulation,
3 = Protanopia Correction , 4 = Deuteranopia Correction , 5 = Tritanopia Correction,
6 = Protanopia Correction + Simulation, 7 = Deuteranopia Correction + Simulation, 8 = Tritanopia Correction + Simulation
severity: 0.0 = off, 1.0 = max, severity of color blindness, red (Protanopia), green (Deuteranopia), or blue (Tritanopia).
0 1 2 simulate what a color-blind person sees (for debug)
3 4 5 are used to actually correct colors (for release)
6 7 8 visualize the effectiveness of the correction (for debug)
Tweaks(hue:0, saturation:1.0, brightness:1.0, contrast:1.0, luminosity:1.0, gamma:1.0, sharpness:0.0)
hue: 0.0 - 360.0, changes hue (HSB/HSV model).
saturation: 0.0 - 10.0, < 1 reduces, > 1 increases saturation (HSB/HSV model).
brightness: 0.0 - 10.0, < 1 reduces, > 1 increases brightness/value (HSB/HSV model).
contrast: 0.0 - 10.0, < 1 reduces, > 1 increases contrast.
luminosity: 0.0 - 10.0, < 1 reduces, > 1 increases luminosity.
gamma: 0.0 - 10.0, < 1 reduces, > 1 increases gamma.
sharpness: 0.0 = off, 10.0 = max
EXE Version
I also provide an executable version that works with other applications.
To use it, simply copy Fullscreen++.exe and .ini into the game directory and run it.
Fullscreen++ will launch the game, capture its window, and redraw the upscaled content inside.
It is preconfigured for RM2k3 but can be used for any software that renders its window using GDI.
Code:
[Fullscreen++]
ApplicationPath=RPG_RT.exe
CommandLineArgs=NormalPlay ShowTitle Window
CreateWindow=false
CaptureRect=2, 2, 640, 480
...
Effect0=SimpleScale(0.5, 0) RAA() SimpleScale()ApplicationPath = path to the executable to launch.
CommandLineArgs = Fullscreen++ requires the game to be in windowed mode, these arguments force 2k3 into windowed mode.
CreateWindow = creates a new window for Fullscreen++, not needed for 2k3 but useful for other software.
CaptureRect = area of the window to capture (2k3 has a gray frame, so I remove it). Leave empty to capture the whole window.
Effect0 = SimpleScale(0.5, 0)... Pixel-art upscalers need the game at x1 size to work properly. Since 2k3’s windowed mode is x2 by default, I downscale without interpolation to restore x1 before applying the other shaders.

Examples with RM2k3 (integrated) and Kega Fusion (separate window).

Notes
The VX Ace video player is not supported for now.
Configuration can be a bit tedious, I will add a GUI in the next update.
Shaders require DirectX 11, non-compatible PCs automatically fall back to the old Fullscreen++ version.