| name | optiscaler-client-integration |
| description | Expert guidance for integrating OptiScaler Client, a C# Windows application that manages AI upscaling (DLSS/FSR/XeSS) and frame generation mods for games |
| triggers | ["how do I use optiscaler client","integrate optiscaler with my game manager","add optiscaler functionality to my app","work with optiscaler client codebase","understand optiscaler client architecture","build features for optiscaler client","contribute to optiscaler client","extend optiscaler client functionality"] |
OptiScaler Client Integration
Skill by ara.so — Devtools Skills collection.
OptiScaler Client is a C# Windows application that automates the installation and management of AI upscaling technologies (DLSS, FSR, XeSS) and frame generation mods for games. It scans game libraries across multiple platforms (Steam, Epic, GOG, etc.), downloads necessary components, and manages configuration profiles.
Project Overview
Repository: optiscalerclient/optiscaler-client
Language: C# (WPF/Windows Forms)
License: MIT (note: README mentions GPL v3, but metadata shows MIT)
Platform: Windows 10/11 (with limited Linux Steam support)
Core Capabilities
- Multi-platform game library scanning (Steam, Epic, GOG, EA, Ubisoft, Battle.net, Xbox)
- Automatic download and installation of OptiScaler, Fakenvapi, and frame generation mods
- Profile-based INI configuration management
- DLL injection method selection (dxgi, winmm, d3d12, etc.)
- GPU detection and component selection logic
- Backup/restore system for game files
- Localization support (14 languages)
Installation & Setup
For Users
- Download from releases:
https://github.com/optiscalerclient/optiscaler-client/releases/download/Optiscaler/optiscaler-client.zip
- Extract and run
OptiscalerClient.exe (self-contained, no .NET runtime needed)
For Developers
git clone https://github.com/optiscalerclient/optiscaler-client.git
cd optiscaler-client
Architecture Patterns
Game Discovery System
The scanner system likely uses multiple provider classes:
public interface IGameScanner
{
Task<List<GameEntry>> ScanAsync(CancellationToken cancellationToken);
string PlatformName { get; }
bool IsEnabled { get; set; }
}
public class SteamScanner : IGameScanner
{
public string PlatformName => "Steam";
public async Task<List<GameEntry>> ScanAsync(CancellationToken ct)
{
var games = new List<GameEntry>();
string steamPath = GetSteamInstallPath();
string vdfPath = Path.Combine(steamPath, "steamapps", "libraryfolders.vdf");
var libraries = ParseLibraryFolders(vdfPath);
foreach (var library in libraries)
{
var acfFiles = Directory.GetFiles(
Path.Combine(library, "steamapps"),
"appmanifest_*.acf"
);
foreach (var acfFile in acfFiles)
{
var game = ParseAppManifest(acfFile);
if (game != null && !IsExcluded(game.Name))
{
games.Add(game);
}
}
}
games;
}
{
key = Registry.LocalMachine.OpenSubKey(
);
key?.GetValue()
?? ;
}
}
Component Download & Installation
public class ComponentManager
{
private readonly HttpClient _httpClient;
private readonly string _cacheDirectory;
public ComponentManager(string cacheDir)
{
_cacheDirectory = cacheDir;
_httpClient = new HttpClient();
ConfigureProxy();
}
public async Task<string> DownloadOptiScalerAsync(
string version,
bool isBeta,
IProgress<double> progress,
CancellationToken ct
)
{
string cacheKey = $"optiscaler_{version}_{(isBeta ? "beta" : "stable")}";
string cachePath = Path.Combine(_cacheDirectory, cacheKey);
if (Directory.Exists(cachePath))
{
return cachePath;
}
string url = isBeta
? $"https://github.com/optiscaler/OptiScaler/releases/download/beta-{version}/OptiScaler.zip"
: $"https://github.com/optiscaler/OptiScaler/releases/download/v{version}/OptiScaler.zip";
string zipPath = Path.Combine(_cacheDirectory, $"{cacheKey}.zip");
( response = _httpClient.GetAsync(url, HttpCompletionOption.ResponseHeadersRead, ct))
{
response.EnsureSuccessStatusCode();
totalBytes = response.Content.Headers.ContentLength ?? ;
contentStream = response.Content.ReadAsStreamAsync(ct);
fileStream = FileStream(zipPath, FileMode.Create, FileAccess.Write, FileShare.None);
buffer = [];
totalRead = ;
bytesRead;
((bytesRead = contentStream.ReadAsync(buffer, , buffer.Length, ct)) > )
{
fileStream.WriteAsync(buffer, , bytesRead, ct);
totalRead += bytesRead;
(totalBytes > )
{
progress?.Report(()totalRead / totalBytes * );
}
}
}
ZipFile.ExtractToDirectory(zipPath, cachePath);
File.Delete(zipPath);
cachePath;
}
{
proxyUrl = Environment.GetEnvironmentVariable()
?? Environment.GetEnvironmentVariable();
(!.IsNullOrEmpty(proxyUrl))
{
proxy = WebProxy(proxyUrl);
handler = HttpClientHandler { Proxy = proxy };
_httpClient = HttpClient(handler);
}
}
}
Game Installation Logic
public class GameInstaller
{
public async Task<InstallResult> InstallOptiScalerAsync(
GameEntry game,
InstallOptions options,
CancellationToken ct
)
{
string targetExe = options.ManualPath ?? DetectMainExecutable(game.InstallPath);
string gameDir = Path.GetDirectoryName(targetExe);
string backupDir = Path.Combine(gameDir, ".optiscaler_backup");
Directory.CreateDirectory(backupDir);
string injectionDll = options.InjectionMethod;
string originalDll = Path.Combine(gameDir, injectionDll);
if (File.Exists(originalDll))
{
File.Copy(originalDll, Path.Combine(backupDir, injectionDll), true);
}
string optiScalerPath = await _componentManager.DownloadOptiScalerAsync(
options.OptiScalerVersion,
options.UseBeta,
options.Progress,
ct
);
CopyOptiScalerFiles(optiScalerPath, gameDir);
File.Copy(
Path.Combine(optiScalerPath, "nvngx.dll"),
Path.Combine(gameDir, injectionDll),
overwrite: true
);
if (options.NeedsFakenvapi)
{
await InstallFakenaviAsync(gameDir, options.FakenaviVersion, ct);
}
if (options.InstallFrameGen)
{
InstallNukemFGAsync(gameDir, ct);
}
(!.IsNullOrEmpty(options.ProfileName))
{
ApplyProfileAsync(gameDir, options.ProfileName);
}
(options.InstallOptiPatcher)
{
ConfigureOptiPatcherAsync(gameDir);
}
InstallResult
{
Success = ,
InstalledComponents = GetInstalledComponents(gameDir)
};
}
{
phoenixDirs = [] { , };
( subDir phoenixDirs)
{
path = Path.Combine(installPath, subDir);
(Directory.Exists(path))
{
exes = Directory.GetFiles(path, , SearchOption.TopDirectoryOnly)
.Where(f => !f.Contains() && !f.Contains())
.ToList();
(exes.Any())
{
exes.First();
}
}
}
candidates = Directory.GetFiles(installPath, , SearchOption.AllDirectories)
.Where(f => !IsSystemExecutable(f))
.OrderByDescending(f => FileInfo(f).Length)
.ToList();
candidates.FirstOrDefault();
}
{
excludeNames = []
{
, , , ,
, , ,
};
fileName = Path.GetFileNameWithoutExtension(path).ToLower();
excludeNames.Any(e => fileName.Contains(e));
}
}
Profile Management
public class ProfileManager
{
private readonly string _profilesDirectory;
public ProfileManager(string profilesDir)
{
_profilesDirectory = profilesDir;
Directory.CreateDirectory(_profilesDirectory);
}
public Profile LoadProfile(string name)
{
string path = Path.Combine(_profilesDirectory, $"{name}.ini");
if (!File.Exists(path))
{
throw new FileNotFoundException($"Profile '{name}' not found");
}
var profile = new Profile { Name = name };
var parser = new IniParser();
var data = parser.ReadFile(path);
foreach (var section in data.Sections)
{
profile.Sections[section.SectionName] = section.Keys
.ToDictionary(k => k.KeyName, k => k.Value);
}
return profile;
}
public void SaveProfile(Profile profile)
{
string path = Path.Combine(_profilesDirectory, $"{profile.Name}.ini");
using var writer = new StreamWriter(path);
( section profile.Sections)
{
writer.WriteLine();
( kvp section.Value)
{
writer.WriteLine();
}
writer.WriteLine();
}
}
{
Profile
{
Name = ,
Sections = Dictionary<, Dictionary<, >>
{
[] = ()
{
[] = ,
[] = ,
[] =
},
[] = ()
{
[] = ,
[] =
},
[] = ()
{
[] = ,
[] = ,
[] =
}
}
};
}
}
{
Name { ; ; }
Dictionary<, Dictionary<, >> Sections { ; ; } = ();
}
GPU Detection
public class GpuDetector
{
public List<GpuInfo> DetectGpus()
{
var gpus = new List<GpuInfo>();
try
{
using var searcher = new ManagementObjectSearcher(
"SELECT * FROM Win32_VideoController"
);
foreach (ManagementObject obj in searcher.Get())
{
var name = obj["Name"]?.ToString();
var vendor = obj["AdapterCompatibility"]?.ToString();
var driverVersion = obj["DriverVersion"]?.ToString();
if (string.IsNullOrEmpty(name))
continue;
var gpu = new GpuInfo
{
Name = name,
Vendor = DetermineVendor(name, vendor),
DriverVersion = driverVersion,
IsDiscrete = IsDiscreteGpu(name)
};
gpus.Add(gpu);
}
}
catch (Exception ex)
{
Console.WriteLine($"WMI detection failed: {ex.Message}");
}
return gpus
.OrderByDescending(g => g.IsDiscrete)
.ThenBy(g => g.Vendor == GpuVendor.NVIDIA ? 0 :
g.Vendor == GpuVendor.AMD ? 1 : 2)
.ToList();
}
{
name = name.ToLower();
vendor = vendor?.ToLower() ?? ;
(name.Contains() || name.Contains() || name.Contains())
GpuVendor.NVIDIA;
(name.Contains() || name.Contains() || name.Contains())
GpuVendor.AMD;
(name.Contains() || name.Contains() || name.Contains())
GpuVendor.Intel;
GpuVendor.Unknown;
}
{
name = name.ToLower();
!name.Contains() || name.Contains();
}
{
gpu.Vendor == GpuVendor.AMD || gpu.Vendor == GpuVendor.Intel;
}
}
GpuVendor { NVIDIA, AMD, Intel, Unknown }
{
Name { ; ; }
GpuVendor Vendor { ; ; }
DriverVersion { ; ; }
IsDiscrete { ; ; }
}
Configuration Management
Application Settings
public class AppSettings
{
private readonly string _settingsPath;
public AppSettings()
{
string appData = Environment.GetFolderPath(
Environment.SpecialFolder.LocalApplicationData
);
string appDir = Path.Combine(appData, "OptiScalerClient");
Directory.CreateDirectory(appDir);
_settingsPath = Path.Combine(appDir, "settings.json");
}
public Settings Load()
{
if (!File.Exists(_settingsPath))
{
return new Settings();
}
string json = File.ReadAllText(_settingsPath);
return JsonSerializer.Deserialize<Settings>(json) ?? new Settings();
}
public void Save(Settings settings)
{
var options = new JsonSerializerOptions
{
WriteIndented = true
};
string json = JsonSerializer.Serialize(settings, options);
File.WriteAllText(_settingsPath, json);
}
}
public class Settings
{
public string Language { get; set; } = "en";
public bool ShowBetaVersions { get; set; } = false;
DefaultOptiScalerVersion { ; ; } = ;
DefaultInjectionMethod { ; ; } = ;
DefaultProfile { ; ; } = ;
PreferredGpuName { ; ; }
Dictionary<, > EnabledScanners { ; ; } = ()
{
[] = ,
[] = ,
[] = ,
[] = ,
[] = ,
[] = ,
[] =
};
List<> CustomScanPaths { ; ; } = ();
EnableAnimations { ; ; } = ;
ProxyUrl { ; ; }
ProxyUsername { ; ; }
SteamGridDbApiKey { ; ; }
WindowState WindowState { ; ; } = ();
}
{
Width { ; ; } = ;
Height { ; ; } = ;
X { ; ; } = ;
Y { ; ; } = ;
Maximized { ; ; } = ;
}
Common Usage Patterns
Bulk Installation
public async Task BulkInstallAsync(
List<GameEntry> games,
BulkInstallOptions options,
IProgress<BulkProgress> progress,
CancellationToken ct
)
{
var results = new List<BulkInstallResult>();
int completed = 0;
foreach (var game in games)
{
if (ct.IsCancellationRequested)
break;
try
{
var installOptions = new InstallOptions
{
OptiScalerVersion = options.OptiScalerVersion,
InjectionMethod = options.InjectionMethod,
ProfileName = options.ProfileName,
NeedsFakenvapi = _gpuDetector.NeedsFakenvapi(options.SelectedGpu),
InstallFrameGen = options.InstallFrameGen,
UseBeta = options.UseBeta
};
var result = await _installer.InstallOptiScalerAsync(
game,
installOptions,
ct
);
results.Add(new BulkInstallResult
{
GameName = game.Name,
Success = result.Success,
Message = result.Success ? "Installed successfully" : result.ErrorMessage
});
}
catch (Exception ex)
{
results.Add(new BulkInstallResult
{
GameName = game.Name,
Success = false,
Message = ex.Message
});
}
completed++;
progress?.Report(new BulkProgress
{
Current = completed,
Total = games.Count,
CurrentGame = game.Name,
Results = results
});
}
}
Technology Detection
public class TechnologyDetector
{
public GameTechnologies DetectTechnologies(string gameDirectory)
{
var tech = new GameTechnologies();
var dlssDlls = Directory.GetFiles(gameDirectory, "nvngx_dlss.dll", SearchOption.AllDirectories);
if (dlssDlls.Any())
{
tech.HasDLSS = true;
tech.DLSSVersion = GetDllVersion(dlssDlls.First());
}
var dlssgDlls = Directory.GetFiles(gameDirectory, "nvngx_dlssg.dll", SearchOption.AllDirectories);
if (dlssgDlls.Any())
{
tech.HasDLSSG = true;
tech.DLSSGVersion = GetDllVersion(dlssgDlls.First());
}
var fsrDlls = Directory.GetFiles(gameDirectory, "amd_fidelityfx_*", SearchOption.AllDirectories);
if (fsrDlls.Any())
{
tech.HasFSR = true;
tech.FSRVersion = ParseFSRVersion(fsrDlls.First());
}
var xessDlls = Directory.GetFiles(gameDirectory, "libxess.dll", SearchOption.AllDirectories);
if (xessDlls.Any())
{
tech.HasXeSS = true;
tech.XeSSVersion = GetDllVersion(xessDlls.First());
}
return tech;
}
private string GetDllVersion(string dllPath)
{
{
versionInfo = FileVersionInfo.GetVersionInfo(dllPath);
versionInfo.FileVersion ?? ;
}
{
;
}
}
}
{
HasDLSS { ; ; }
DLSSVersion { ; ; }
HasDLSSG { ; ; }
DLSSGVersion { ; ; }
HasFSR { ; ; }
FSRVersion { ; ; }
HasXeSS { ; ; }
XeSSVersion { ; ; }
}
Troubleshooting
Common Issues
Game not detected during scan:
- Verify platform scanner is enabled in Settings
- Add custom scan path if game is in non-standard location
- Use "Add Manually" and select game executable directly
- Check that game is not in exclusion list
Download failures:
- Check proxy configuration if behind corporate firewall
- Verify GitHub is accessible from your network
- Set environment variables:
HTTP_PROXY and HTTPS_PROXY
- Check antivirus isn't blocking downloads
Installation fails:
- Ensure game is not running during installation
- Check that you have write permissions to game directory
- For protected system folders (Program Files), run as Administrator
- Verify sufficient disk space for components (~500MB per install)
False positive antivirus warnings:
- Add exception for
OptiscalerClient.exe in Windows Defender
- Whitelist the cache directory (typically
%LOCALAPPDATA%\OptiScalerClient\cache)
- Download only from official GitHub releases
- Verify file hash if concerned about tampering
Debug Logging
public class Logger
{
private readonly string _logPath;
public Logger()
{
string appData = Environment.GetFolderPath(
Environment.SpecialFolder.LocalApplicationData
);
string logDir = Path.Combine(appData, "OptiScalerClient", "logs");
Directory.CreateDirectory(logDir);
_logPath = Path.Combine(
logDir,
$"optiscaler_{DateTime.Now:yyyyMMdd_HHmmss}.log"
);
}
public void Log(LogLevel level, string message, Exception ex = null)
{
string timestamp = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
string logLine = $"[{timestamp}] [{level}] {message}";
if (ex != null)
{
logLine += $"\n{ex}";
}
File.AppendAllText(_logPath, logLine + "\n");
Debug.WriteLine(logLine);
}
}
public enum LogLevel { Debug, Info, Warning, Error }
Backup Recovery
public class BackupManager
{
public void RestoreBackup(string gameDirectory)
{
string backupDir = Path.Combine(gameDirectory, ".optiscaler_backup");
if (!Directory.Exists(backupDir))
{
throw new DirectoryNotFoundException("No backup found for this game");
}
var backupFiles = Directory.GetFiles(backupDir);
foreach (var backupFile in backupFiles)
{
string fileName = Path.GetFileName(backupFile);
string targetPath = Path.Combine(gameDirectory, fileName);
File.Copy(backupFile, targetPath, overwrite: true);
}
DeleteOptiScalerFiles(gameDirectory);
Directory.Delete(backupDir, recursive: true);
}
}
API Integrations
SteamGridDB Cover Art
public class CoverArtFetcher
{
private readonly HttpClient _httpClient;
private readonly string _apiKey;
private readonly string _cacheDir;
public CoverArtFetcher(string apiKey, string cacheDir)
{
_apiKey = apiKey;
_cacheDir = cacheDir;
_httpClient = new HttpClient
{
BaseAddress = new Uri("https://www.steamgriddb.com/api/v2/")
};
if (!string.IsNullOrEmpty(_apiKey))
{
_httpClient.DefaultRequestHeaders.Add("Authorization", $"Bearer {_apiKey}");
}
}
public async Task<string> GetCoverArtAsync(int steamAppId)
{
string cachedPath = Path.Combine(_cacheDir, $"{steamAppId}.jpg");
if (File.Exists(cachedPath))
{
return cachedPath;
}
try
{
var gameResponse = await _httpClient.GetAsync($"games/steam/{steamAppId}");
if (!gameResponse.IsSuccessStatusCode)
{
return ;
}
gameData = gameResponse.Content.ReadAsStringAsync();
gameDoc = JsonDocument.Parse(gameData);
(!gameDoc.RootElement.GetProperty().GetBoolean())
{
;
}
gameId = gameDoc.RootElement
.GetProperty()
.GetProperty()
.GetInt32();
gridResponse = _httpClient.GetAsync();
(!gridResponse.IsSuccessStatusCode)
{
;
}
gridData = gridResponse.Content.ReadAsStringAsync();
gridDoc = JsonDocument.Parse(gridData);
grids = gridDoc.RootElement.GetProperty();
(grids.GetArrayLength() == )
{
;
}
imageUrl = grids[].GetProperty().GetString();
imageBytes = _httpClient.GetByteArrayAsync(imageUrl);
File.WriteAllBytesAsync(cachedPath, imageBytes);
cachedPath;
}
(Exception ex)
{
Debug.WriteLine();
;
}
}
}
Testing Patterns
Unit Test Example
[TestClass]
public class GpuDetectorTests
{
[TestMethod]
public void NeedsFakenvapi_NvidiaGpu_ReturnsFalse()
{
var detector = new GpuDetector();
var gpu = new GpuInfo
{
Name = "NVIDIA GeForce RTX 4060",
Vendor = GpuVendor.NVIDIA
};
bool needs = detector.NeedsFakenvapi(gpu);
Assert.IsFalse(needs);
}
[TestMethod]
public void NeedsFakenvapi_AmdGpu_ReturnsTrue()
{
var detector = new GpuDetector();
var gpu = new GpuInfo
{
Name = "AMD Radeon RX 7900 XT",
Vendor = GpuVendor.AMD
};
bool needs = detector.NeedsFakenvapi(gpu);
Assert.IsTrue(needs);
}
}
This skill covers the core architecture patterns, installation flows, and integration points for working with or extending OptiScaler Client. Use these patterns as a foundation when adding features or troubleshooting issues.