Update to latest util versions, restore SmokeAPI

Utilities have been updated to the latest versions. The ability to use SmokeAPI instead of CreamAPI has been restored, and a checkbox has been added to switch between them.
This commit is contained in:
Soul Shard
2025-10-01 06:07:54 +07:00
parent 12e9a4b66f
commit c8a65f35bf
64 changed files with 355 additions and 86 deletions
+38
View File
@@ -0,0 +1,38 @@
name: Autobuild
on:
push:
branches: [ main ]
tags:
- '*'
workflow_dispatch:
pull_request:
types: [ main ]
jobs:
build:
runs-on: windows-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Setup .NET
uses: actions/setup-dotnet@v4
with:
dotnet-version: '8.0.x'
- name: Restore dependencies
run: dotnet restore CreamInstaller.sln
- name: Build Release
run: dotnet build CreamInstaller.sln --configuration Release --no-restore
- name: Publish single-file
run: dotnet publish CreamInstaller.sln -c Release -r win-x64 -p:PublishSingleFile=true --self-contained true --output ./publish
- name: Upload artifact
uses: actions/upload-artifact@v4
with:
name: CreamInstaller-release
path: ./publish/CreamInstaller.exe
+1 -1
View File
@@ -52,7 +52,7 @@ internal class CustomForm : Form
"Automatically finds all installed Steam, Epic and Ubisoft games with their respective DLC-related DLL locations on the user's computer,\n"
+ "parses SteamCMD, Steam Store and Epic Games Store for user-selected games' DLCs, then provides a very simple graphical interface\n"
+ "utilizing the gathered information for the maintenance of DLC unlockers.\n\n"
+ $"The program utilizes the latest version of [CreamAPI](https://cs.rin.ru/forum/viewtopic.php?f=29&t=70576) by [deadmau5](https://cs.rin.ru/forum/viewtopic.php?f=29&t=70576). It also utilizes the latest versions of [Koaloader]({acidicoala}/Koaloader), [ScreamAPI]({acidicoala}/ScreamAPI), [Uplay R1\n"
+ $"The program utilizes the latest version of [CreamAPI](https://cs.rin.ru/forum/viewtopic.php?f=29&t=70576) by [deadmau5](https://cs.rin.ru/forum/viewtopic.php?f=29&t=70576). It also utilizes the latest versions of [SmokeAPI]({acidicoala}/SmokeAPI), [Koaloader]({acidicoala}/Koaloader), [ScreamAPI]({acidicoala}/ScreamAPI), [Uplay R1\n"
+ $"Unlocker]({acidicoala}/UplayR1Unlocker) and [Uplay R2 Unlocker]({acidicoala}/UplayR2Unlocker), all by [acidicoala]({acidicoala}). All unlockers are downloaded and embedded into the program itself; no further\n"
+ "downloads necessary on your part!\n\n"
+ "USAGE:\n" + " 1. Choose which programs and/or games the program should scan for DLC.\n"
+1 -1
View File
@@ -4,7 +4,7 @@
<TargetFramework>net8.0-windows10.0.22621.0</TargetFramework>
<UseWindowsForms>True</UseWindowsForms>
<ApplicationIcon>Resources\program.ico</ApplicationIcon>
<Version>5.0.1.0</Version>
<Version>5.0.1.1</Version>
<Copyright>2021, pointfeev (https://github.com/pointfeev)</Copyright>
<Company>CreamInstaller</Company>
<Product>Automatic DLC Unlocker Installer &amp; Configuration Generator</Product>
+74 -25
View File
@@ -68,6 +68,9 @@ internal sealed partial class InstallForm : CustomForm
bool useCreamApiProxy = selection.UseProxy && !Program.UseSmokeAPI &&
(selection.Platform is Platform.Steam || selection.Platform is Platform.Paradox &&
selection.ExtraSelections.Any(s => s.Platform is Platform.Steam));
bool useSmokeApiProxy = selection.UseProxy && Program.UseSmokeAPI &&
(selection.Platform is Platform.Steam || selection.Platform is Platform.Paradox &&
selection.ExtraSelections.Any(s => s.Platform is Platform.Steam));
UpdateUser(
$"{(uninstalling ? "Uninstalling" : "Installing")}" + $" {(uninstalling ? "from" : "for")} " +
@@ -84,7 +87,7 @@ internal sealed partial class InstallForm : CustomForm
if (Program.Canceled)
return;
directory.GetKoaloaderComponents(out string old_config, out string config);
directory.GetKoaloaderComponents(out string old_config, out string config, out _);
if (directory.GetKoaloaderProxies().Any(proxy =>
proxy.FileExists() && proxy.IsResourceFile(ResourceIdentifier.Koaloader))
|| directory != selection.RootDirectory &&
@@ -97,19 +100,36 @@ internal sealed partial class InstallForm : CustomForm
await Koaloader.Uninstall(directory, selection.RootDirectory, this);
}
directory.GetCreamApiComponents(out _, out _, out _, out _, out config);
if (directory.GetCreamApiProxies().Any(proxy =>
proxy.FileExists() && (proxy.IsResourceFile(ResourceIdentifier.Steamworks32) ||
proxy.IsResourceFile(ResourceIdentifier.Steamworks64))))
if (!Program.UseSmokeAPI)
{
UpdateUser(
"Uninstalling CreamAPI in proxy mode from " + selection.Name +
$" in incorrect directory \"{directory}\" . . . ", LogTextBox.Operation);
await CreamAPI.ProxyUninstall(directory, this);
directory.GetCreamApiComponents(out _, out _, out _, out _, out config);
if (directory.GetCreamApiProxies().Any(proxy =>
proxy.FileExists() && (proxy.IsResourceFile(ResourceIdentifier.Steamworks32) ||
proxy.IsResourceFile(ResourceIdentifier.Steamworks64))))
{
UpdateUser(
"Uninstalling CreamAPI in proxy mode from " + selection.Name +
$" in incorrect directory \"{directory}\" . . . ", LogTextBox.Operation);
await CreamAPI.ProxyUninstall(directory, this);
}
}
else
{
directory.GetSmokeApiComponents(out _, out _, out _, out _, out old_config, out config, out _,
out _, out _);
if (directory.GetSmokeApiProxies().Any(proxy =>
proxy.FileExists() && (proxy.IsResourceFile(ResourceIdentifier.Steamworks32) ||
proxy.IsResourceFile(ResourceIdentifier.Steamworks64))))
{
UpdateUser(
"Uninstalling SmokeAPI in proxy mode from " + selection.Name +
$" in incorrect directory \"{directory}\" . . . ", LogTextBox.Operation);
await SmokeAPI.ProxyUninstall(directory, this);
}
}
}
if (uninstalling || !useKoaloader || !useCreamApiProxy)
if (uninstalling || !useKoaloader || !useCreamApiProxy || !useSmokeApiProxy)
foreach ((string directory, _) in selection.ExecutableDirectories)
{
if (Program.Canceled)
@@ -117,7 +137,7 @@ internal sealed partial class InstallForm : CustomForm
if (uninstalling || !useKoaloader)
{
directory.GetKoaloaderComponents(out string old_config, out string config);
directory.GetKoaloaderComponents(out string old_config, out string config, out _);
if (directory.GetKoaloaderProxies().Any(proxy =>
proxy.FileExists() && proxy.IsResourceFile(ResourceIdentifier.Koaloader))
|| Koaloader.AutoLoadDLLs.Any(pair => (directory + @"\" + pair.dll).FileExists()) ||
@@ -130,23 +150,44 @@ internal sealed partial class InstallForm : CustomForm
}
}
if (uninstalling || !useCreamApiProxy)
if (!Program.UseSmokeAPI)
{
directory.GetCreamApiComponents(out _, out _, out _, out _, out string config);
if (directory.GetCreamApiProxies().Any(proxy =>
proxy.FileExists() && (proxy.IsResourceFile(ResourceIdentifier.Steamworks32) ||
proxy.IsResourceFile(ResourceIdentifier.Steamworks64))) ||
config.FileExists())
if (uninstalling || !useCreamApiProxy)
{
UpdateUser(
"Uninstalling CreamAPI in proxy mode from " + selection.Name +
$" in directory \"{directory}\" . . . ", LogTextBox.Operation);
await CreamAPI.ProxyUninstall(directory, this);
directory.GetCreamApiComponents(out _, out _, out _, out _, out string config);
if (directory.GetCreamApiProxies().Any(proxy =>
proxy.FileExists() && (proxy.IsResourceFile(ResourceIdentifier.Steamworks32) ||
proxy.IsResourceFile(ResourceIdentifier.Steamworks64))) ||
config.FileExists())
{
UpdateUser(
"Uninstalling CreamAPI in proxy mode from " + selection.Name +
$" in directory \"{directory}\" . . . ", LogTextBox.Operation);
await CreamAPI.ProxyUninstall(directory, this);
}
}
}
else
{
if (uninstalling || !useSmokeApiProxy)
{
directory.GetSmokeApiComponents(out _, out _, out _, out _, out string old_config, out string config, out _,
out _, out _);
if (directory.GetSmokeApiProxies().Any(proxy =>
proxy.FileExists() && (proxy.IsResourceFile(ResourceIdentifier.Steamworks32) ||
proxy.IsResourceFile(ResourceIdentifier.Steamworks64))) ||
config.FileExists())
{
UpdateUser(
"Uninstalling SmokeAPI in proxy mode from " + selection.Name +
$" in directory \"{directory}\" . . . ", LogTextBox.Operation);
await SmokeAPI.ProxyUninstall(directory, this);
}
}
}
}
bool uninstallingForProxy = uninstalling || useKoaloader || useCreamApiProxy;
bool uninstallingForProxy = uninstalling || useKoaloader || useCreamApiProxy || useSmokeApiProxy;
int count = selection.DllDirectories.Count, cur = 0;
foreach (string directory in selection.DllDirectories)
{
@@ -199,7 +240,7 @@ internal sealed partial class InstallForm : CustomForm
if (selection.Platform is Platform.Epic or Platform.Paradox)
{
directory.GetScreamApiComponents(out string api32, out string api32_o, out string api64,
out string api64_o, out string config, out string log);
out string api64_o, out string old_config, out string config, out string old_log, out string log);
if (uninstallingForProxy
? api32_o.FileExists() || api64_o.FileExists() || config.FileExists() || log.FileExists()
: api32.FileExists() || api64.FileExists())
@@ -253,13 +294,13 @@ internal sealed partial class InstallForm : CustomForm
UpdateProgress(++cur / count * 100);
}
if ((useCreamApiProxy || useKoaloader) && !uninstalling)
if ((useCreamApiProxy || useSmokeApiProxy || useKoaloader) && !uninstalling)
foreach ((string directory, BinaryType binaryType) in selection.ExecutableDirectories)
{
if (Program.Canceled)
return;
if (useCreamApiProxy)
if (useCreamApiProxy && !Program.UseSmokeAPI)
{
UpdateUser(
"Installing CreamAPI in proxy mode for " + selection.Name +
@@ -267,6 +308,14 @@ internal sealed partial class InstallForm : CustomForm
LogTextBox.Operation);
await CreamAPI.ProxyInstall(directory, binaryType, selection, this);
}
else if (useSmokeApiProxy && Program.UseSmokeAPI)
{
UpdateUser(
"Installing SmokeAPI in proxy mode for " + selection.Name +
$" in directory \"{directory}\" . . . ",
LogTextBox.Operation);
await SmokeAPI.ProxyInstall(directory, binaryType, selection, this);
}
else if (useKoaloader)
{
UpdateUser("Installing Koaloader for " + selection.Name + $" in directory \"{directory}\" . . . ",
+54 -4
View File
@@ -1,8 +1,8 @@
using System.ComponentModel;
using CreamInstaller.Components;
using CreamInstaller.Resources;
using System.ComponentModel;
using System.Windows.Forms;
using CreamInstaller.Components;
namespace CreamInstaller.Forms
{
partial class SelectForm
@@ -28,6 +28,9 @@ namespace CreamInstaller.Forms
blockedGamesFlowPanel = new FlowLayoutPanel();
blockedGamesCheckBox = new CheckBox();
blockProtectedHelpButton = new Button();
useSmokeAPILayoutPanel = new FlowLayoutPanel();
useSmokeAPICheckBox = new CheckBox();
useSmokeAPIHelpButton = new Button();
allCheckBoxLayoutPanel = new FlowLayoutPanel();
allCheckBox = new CheckBox();
progressBar = new ProgressBar();
@@ -45,6 +48,7 @@ namespace CreamInstaller.Forms
programsGroupBox.SuspendLayout();
proxyFlowPanel.SuspendLayout();
blockedGamesFlowPanel.SuspendLayout();
useSmokeAPILayoutPanel.SuspendLayout();
allCheckBoxLayoutPanel.SuspendLayout();
saveFlowPanel.SuspendLayout();
SuspendLayout();
@@ -84,6 +88,7 @@ namespace CreamInstaller.Forms
programsGroupBox.Controls.Add(proxyFlowPanel);
programsGroupBox.Controls.Add(noneFoundLabel);
programsGroupBox.Controls.Add(blockedGamesFlowPanel);
programsGroupBox.Controls.Add(useSmokeAPILayoutPanel);
programsGroupBox.Controls.Add(allCheckBoxLayoutPanel);
programsGroupBox.Controls.Add(selectionTreeView);
programsGroupBox.Location = new System.Drawing.Point(12, 12);
@@ -172,6 +177,48 @@ namespace CreamInstaller.Forms
blockProtectedHelpButton.UseVisualStyleBackColor = true;
blockProtectedHelpButton.Click += OnBlockProtectedGamesHelpButtonClicked;
//
// useSmokeAPILayoutPanel
//
useSmokeAPILayoutPanel.Anchor = AnchorStyles.Top;
useSmokeAPILayoutPanel.AutoSize = true;
useSmokeAPILayoutPanel.AutoSizeMode = AutoSizeMode.GrowAndShrink;
useSmokeAPILayoutPanel.Controls.Add(useSmokeAPICheckBox);
useSmokeAPILayoutPanel.Controls.Add(useSmokeAPIHelpButton);
useSmokeAPILayoutPanel.Location = new System.Drawing.Point(338, -1);
useSmokeAPILayoutPanel.Margin = new Padding(0);
useSmokeAPILayoutPanel.Name = "useSmokeAPILayoutPanel";
useSmokeAPILayoutPanel.Size = new System.Drawing.Size(124, 19);
useSmokeAPILayoutPanel.TabIndex = 1006;
useSmokeAPILayoutPanel.WrapContents = false;
//
// useSmokeAPICheckBox
//
useSmokeAPICheckBox.AutoSize = true;
useSmokeAPICheckBox.Checked = true;
useSmokeAPICheckBox.CheckState = CheckState.Checked;
useSmokeAPICheckBox.Enabled = false;
useSmokeAPICheckBox.Location = new System.Drawing.Point(2, 0);
useSmokeAPICheckBox.Margin = new Padding(2, 0, 0, 0);
useSmokeAPICheckBox.Name = "useSmokeAPICheckBox";
useSmokeAPICheckBox.Size = new System.Drawing.Size(102, 19);
useSmokeAPICheckBox.TabIndex = 1;
useSmokeAPICheckBox.Text = "Use SmokeAPI";
useSmokeAPICheckBox.UseVisualStyleBackColor = true;
useSmokeAPICheckBox.CheckedChanged += OnUseSmokeAPICheckBoxChanged;
//
// useSmokeAPIHelpButton
//
useSmokeAPIHelpButton.Enabled = false;
useSmokeAPIHelpButton.Font = new System.Drawing.Font("Segoe UI", 7F);
useSmokeAPIHelpButton.Location = new System.Drawing.Point(104, 0);
useSmokeAPIHelpButton.Margin = new Padding(0, 0, 1, 0);
useSmokeAPIHelpButton.Name = "useSmokeAPIHelpButton";
useSmokeAPIHelpButton.Size = new System.Drawing.Size(19, 19);
useSmokeAPIHelpButton.TabIndex = 2;
useSmokeAPIHelpButton.Text = "?";
useSmokeAPIHelpButton.UseVisualStyleBackColor = true;
useSmokeAPIHelpButton.Click += OnUseSmokeAPIHelpButtonClicked;
//
// allCheckBoxLayoutPanel
//
allCheckBoxLayoutPanel.Anchor = AnchorStyles.Top | AnchorStyles.Right;
@@ -182,7 +229,7 @@ namespace CreamInstaller.Forms
allCheckBoxLayoutPanel.Margin = new Padding(0);
allCheckBoxLayoutPanel.Name = "allCheckBoxLayoutPanel";
allCheckBoxLayoutPanel.Size = new System.Drawing.Size(42, 19);
allCheckBoxLayoutPanel.TabIndex = 1006;
allCheckBoxLayoutPanel.TabIndex = 1007;
allCheckBoxLayoutPanel.WrapContents = false;
//
// allCheckBox
@@ -404,7 +451,10 @@ namespace CreamInstaller.Forms
private CustomTreeView selectionTreeView;
private CheckBox blockedGamesCheckBox;
private Button blockProtectedHelpButton;
private CheckBox useSmokeAPICheckBox;
private Button useSmokeAPIHelpButton;
private FlowLayoutPanel blockedGamesFlowPanel;
private FlowLayoutPanel useSmokeAPILayoutPanel;
private FlowLayoutPanel allCheckBoxLayoutPanel;
private Button uninstallButton;
private Label progressLabelGames;
+20 -2
View File
@@ -548,6 +548,8 @@ internal sealed partial class SelectForm : CustomForm
Program.Canceled = false;
blockedGamesCheckBox.Enabled = false;
blockProtectedHelpButton.Enabled = false;
useSmokeAPICheckBox.Enabled = false;
useSmokeAPIHelpButton.Enabled = false;
cancelButton.Enabled = true;
scanButton.Enabled = false;
noneFoundLabel.Visible = false;
@@ -694,6 +696,8 @@ internal sealed partial class SelectForm : CustomForm
scanButton.Enabled = true;
blockedGamesCheckBox.Enabled = true;
blockProtectedHelpButton.Enabled = true;
useSmokeAPICheckBox.Enabled = true;
useSmokeAPIHelpButton.Enabled = true;
}
private void OnTreeViewNodeCheckedChanged(object sender, TreeViewEventArgs e)
@@ -887,8 +891,8 @@ internal sealed partial class SelectForm : CustomForm
foreach (string directory in directories)
{
directory.GetScreamApiComponents(out string api32, out string api32_o, out string api64,
out string api64_o, out string config,
out string log);
out string api64_o, out string old_config, out string config,
out string old_log, out string log);
if (api32.FileExists() || api32_o.FileExists() || api64.FileExists() || api64_o.FileExists() ||
config.FileExists() || log.FileExists())
_ = items.Add(new ContextMenuItem($"Open EOS Directory #{++epic}", "File Explorer",
@@ -1206,6 +1210,20 @@ internal sealed partial class SelectForm : CustomForm
: blockedDirectoryExceptions),
customFormText: "Block Protected Games");
}
private void OnUseSmokeAPICheckBoxChanged(object sender, EventArgs e)
{
Program.UseSmokeAPI = useSmokeAPICheckBox.Checked;
OnLoad(forceProvideChoices: false);
}
private void OnUseSmokeAPIHelpButtonClicked(object sender, EventArgs e)
{
using DialogForm form = new(this);
_ = form.Show(SystemIcons.Information,
"InTest restore SmokeAPI in app. May be unstable."
+ "\n\nIf some games don't launch with it - try disable and reinstall unlock",
customFormText: "Use SmokeAPI");
}
private void OnSortCheckBoxChanged(object sender, EventArgs e)
=> selectionTreeView.TreeViewNodeSorter =
+2 -2
View File
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Microsoft ResX Schema
Version 2.0
@@ -48,7 +48,7 @@
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
@@ -111,7 +111,7 @@ internal static class ParadoxLauncher
if (steamOriginalSdk64 is null && api64.FileExists() &&
!api64.IsResourceFile(ResourceIdentifier.Steamworks64))
steamOriginalSdk64 = api64.ReadFileBytes(true);
directory.GetScreamApiComponents(out api32, out api32_o, out api64, out api64_o, out _, out _);
directory.GetScreamApiComponents(out api32, out api32_o, out api64, out api64_o, out _, out _, out _, out _);
screamInstalled = screamInstalled || api32_o.FileExists() || api64_o.FileExists()
|| api32.FileExists() && api32.IsResourceFile(ResourceIdentifier.EpicOnlineServices32)
|| api64.FileExists() && api64.IsResourceFile(ResourceIdentifier.EpicOnlineServices64);
@@ -165,7 +165,7 @@ internal static class ParadoxLauncher
else
await CreamAPI.Install(directory, selection, generateConfig: false);
directory.GetScreamApiComponents(out api32, out _, out api64, out _, out _, out _);
directory.GetScreamApiComponents(out api32, out _, out api64, out _, out _, out _, out _, out _);
if (epicOriginalSdk32 is not null && api32.IsResourceFile(ResourceIdentifier.EpicOnlineServices32))
{
epicOriginalSdk32.WriteResource(api32);
+2 -2
View File
@@ -19,7 +19,7 @@ internal static class Program
? index
: Application.ProductVersion.Length)];
internal const string RepositoryOwner = "FroggMaster";
internal const string RepositoryOwner = "HvTcCore";
internal static readonly string RepositoryName = Name;
internal static readonly string RepositoryPackage = Name + ".zip";
internal static readonly string RepositoryExecutable = Name + ".exe";
@@ -36,7 +36,7 @@ internal static class Program
internal static readonly int CurrentProcessId = CurrentProcess.Id;
// this may forever be false, but who knows, maybe acidicoala makes it once again better than CreamAPI some day
internal const bool UseSmokeAPI = false;
internal static bool UseSmokeAPI = true;
internal static bool BlockProtectedGames = true;
internal static readonly string[] ProtectedGames = ["PAYDAY 2"];
+52 -6
View File
@@ -35,10 +35,11 @@ internal static class Koaloader
into resource
select directory + @"\" + resource;
internal static void GetKoaloaderComponents(this string directory, out string old_config, out string config)
internal static void GetKoaloaderComponents(this string directory, out string old_config, out string config, out string log)
{
old_config = directory + @"\Koaloader.json";
config = directory + @"\Koaloader.config.json";
log = directory + @"\Koaloader.log";
}
private static void WriteProxy(this string path, string proxyName, BinaryType binaryType)
@@ -66,7 +67,7 @@ internal static class Koaloader
private static void CheckConfig(string directory, InstallForm installForm = null)
{
directory.GetKoaloaderComponents(out string old_config, out string config);
directory.GetKoaloaderComponents(out string old_config, out string config, out _);
if (old_config.FileExists())
{
if (!config.FileExists())
@@ -108,6 +109,7 @@ internal static class Koaloader
SortedList<string, string> modules, InstallForm installForm = null)
{
writer.WriteLine("{");
/*writer.WriteLine(" \"$schema\": \"https://raw.githubusercontent.com/acidicoala/Koaloader/refs/tags/v3.0.4/res/Koaloader.schema.json\",");*/
writer.WriteLine(" \"logging\": false,");
writer.WriteLine(" \"enabled\": true,");
writer.WriteLine(" \"auto_load\": " + (modules.Count > 0 ? "false" : "true") + ",");
@@ -122,10 +124,10 @@ internal static class Koaloader
installForm?.UpdateUser($"Added target to Koaloader.json with path {path}", LogTextBox.Action, false);
}
writer.WriteLine(" ]");
writer.WriteLine(" ],");
}
else
writer.WriteLine(" \"targets\": []");
writer.WriteLine(" \"targets\": [],");
if (modules.Count > 0)
{
@@ -153,7 +155,7 @@ internal static class Koaloader
bool deleteConfig = true)
=> await Task.Run(async () =>
{
directory.GetKoaloaderComponents(out string old_config, out string config);
directory.GetKoaloaderComponents(out string old_config, out string config, out string log);
foreach (string proxyPath in directory.GetKoaloaderProxies().Where(proxyPath
=> proxyPath.FileExists() && proxyPath.IsResourceFile(ResourceIdentifier.Koaloader)))
{
@@ -771,7 +773,51 @@ internal static class Koaloader
"85AD3B263735871F4606EF4AB98B9BBC", // Koaloader v3.0.2
"4207947D0452C1E33428ED098DC23D26", // Koaloader v3.0.2
"BDD0DCAE7A5FBBBA0D8B857AC34BD43C", // Koaloader v3.0.2
"A0933D21552CC5C835416DFD7604548D" // Koaloader v3.0.2
"A0933D21552CC5C835416DFD7604548D", // Koaloader v3.0.2
"51C6BF6DA8C9B2E80249A3F74F5F2836", // Koaloader v3.0.4
"9DCB246925667F0C34B306D356AEE8DA", // Koaloader v3.0.4
"1BC45223E417D4AE2A95F46DB71DDD8B", // Koaloader v3.0.4
"0286878E70A95C6AB93F8E2A944501CD", // Koaloader v3.0.4
"FAC5739AF157D3245DEF458D6304D902", // Koaloader v3.0.4
"2EAA174056BFA68AA22C43CBE6388329", // Koaloader v3.0.4
"FA736AC428269ADE76F8795F8104FA39", // Koaloader v3.0.4
"69A71B497A01147744CD204810ABBAD2", // Koaloader v3.0.4
"ABDD0483D79276362A66E48869CFCF6B", // Koaloader v3.0.4
"B544F93FFC46AFD8E5AC3FBA7930DB58", // Koaloader v3.0.4
"6A11F1E24CBD0518EDDEB28A7237CE87", // Koaloader v3.0.4
"7344E1F82B8E8AC08CC135F3858A1C59", // Koaloader v3.0.4
"126DE0C021297F826F91176962B2EDF5", // Koaloader v3.0.4
"2AC92E07DD269C5027A13E3F80C4A89A", // Koaloader v3.0.4
"7EB835E0B131D9A4F3283D15290A16CF", // Koaloader v3.0.4
"0E478B8AACDB2A8ED6038707CFBFC8E4", // Koaloader v3.0.4
"88A12C9B394C5EC2A72BDAE57F10A814", // Koaloader v3.0.4
"F4440A71D0F5D49C1ECC860DE9E3EEE6", // Koaloader v3.0.4
"C74AD1D21DFD141A91B9699DB298FFB3", // Koaloader v3.0.4
"3D7AFD5BAED9BB023A8BAB8715857C45", // Koaloader v3.0.4
"D982F9E2066877C26193109BD0C90815", // Koaloader v3.0.4
"708A3AA98C53CC1E23104544F54C6C22", // Koaloader v3.0.4
"614119A6452F1EC5B855BBBF3D66D6DE", // Koaloader v3.0.4
"D9971AE010AA8262AED30A4376CF32B2", // Koaloader v3.0.4
"045F9154B561705A88DB2F1C6E44D412", // Koaloader v3.0.4
"46629A0974EFFF141C7295B4204F5B60", // Koaloader v3.0.4
"A8AABF2BC2711BA73F9BAFEC9C9D848D", // Koaloader v3.0.4
"FF540D977C0DD9E32D9D452824ECDB96", // Koaloader v3.0.4
"E3F2E6E347BA407D189C8E3DAC58178C", // Koaloader v3.0.4
"383025E324DA842C9F6499E39B1AAB5B", // Koaloader v3.0.4
"20143E97CA1B2B9F729F84FDEE1C0CE4", // Koaloader v3.0.4
"9E6F063F0966C6848E7C15214ACD8774", // Koaloader v3.0.4
"A5EAC4FD9D174EDB8C8570A6FC018254", // Koaloader v3.0.4
"C73B276EBA0B3EBB4ECF0D4BED5E18E6", // Koaloader v3.0.4
"6A6E803C1C8CC93902166BA949FBFF5A", // Koaloader v3.0.4
"6DD915CF4FE47037F9BCBACE2CD36115", // Koaloader v3.0.4
"458AC3E7DD29824A418D23A2B09CC23A", // Koaloader v3.0.4
"F90EB4C46FB1B7ECA985C1CA245F9CBA", // Koaloader v3.0.4
"73F4D0F5C8B3033A04660CD2B27646FC", // Koaloader v3.0.4
"894F5D28EEA75A1F0B8172D0B06FA40E", // Koaloader v3.0.4
"4ECE60B4EAC0461BF33AF0A6359D3679", // Koaloader v3.0.4
"615A6A863A2F8876A1B55B09F5363A03", // Koaloader v3.0.4
"C5BD334FA0DDDD7E5A6FBDBF836C2FE5", // Koaloader v3.0.4
"77E8E2F05AA94D5AB03F5DE506D6B639" // Koaloader v3.0.4
]
};
}
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
+2 -2
View File
@@ -174,8 +174,8 @@ internal static class Resources
if (platform is Platform.Epic or Platform.Paradox)
{
subDirectory.GetScreamApiComponents(out string api32, out string api32_o, out string api64,
out string api64_o, out string config,
out string log);
out string api64_o, out string old_config, out string config,
out string old_log, out string log);
if (api32.FileExists() || api32_o.FileExists() || api64.FileExists() || api64_o.FileExists()
|| (config.FileExists() || log.FileExists()) && !koaloaderInstalled)
_ = dllDirectories.Add(subDirectory);
+26 -22
View File
@@ -14,19 +14,21 @@ internal static class ScreamAPI
{
internal static void GetScreamApiComponents(this string directory, out string api32, out string api32_o,
out string api64, out string api64_o,
out string config, out string log)
out string old_config, out string config, out string old_log, out string log)
{
api32 = directory + @"\EOSSDK-Win32-Shipping.dll";
api32_o = directory + @"\EOSSDK-Win32-Shipping_o.dll";
api64 = directory + @"\EOSSDK-Win64-Shipping.dll";
api64_o = directory + @"\EOSSDK-Win64-Shipping_o.dll";
config = directory + @"\ScreamAPI.json";
log = directory + @"\ScreamAPI.log";
old_config = directory + @"\ScreamAPI.json";
config = directory + @"\ScreamAPI.config.json";
old_log = directory + @"\ScreamAPI.log";
log = directory + @"\ScreamAPI.log.log";
}
internal static void CheckConfig(string directory, Selection selection, InstallForm installForm = null)
{
directory.GetScreamApiComponents(out _, out _, out _, out _, out string config, out _);
directory.GetScreamApiComponents(out _, out _, out _, out _, out string old_config, out string config, out _, out _);
HashSet<SelectionDLC> overrideCatalogItems =
selection.DLC.Where(dlc => dlc.Type is DLCType.Epic && !dlc.Enabled).ToHashSet();
int entitlementCount = 0;
@@ -77,37 +79,37 @@ internal static class ScreamAPI
SortedList<string, SelectionDLC> injectedEntitlements, InstallForm installForm = null)
{
writer.WriteLine("{");
writer.WriteLine(" \"version\": 2,");
/*writer.WriteLine(" \"$schema\": \"https://raw.githubusercontent.com/acidicoala/ScreamAPI/refs/tags/v4.0.0/res/ScreamAPI.schema.json\",");*/
writer.WriteLine(" \"$version\": 3,");
writer.WriteLine(" \"logging\": false,");
writer.WriteLine(" \"eos_logging\": false,");
writer.WriteLine(" \"log_eos\": false,");
writer.WriteLine(" \"block_metrics\": false,");
writer.WriteLine(" \"catalog_items\": {");
writer.WriteLine(" \"unlock_all\": true,");
writer.WriteLine(" \"namespace_id\": \"\",");
writer.WriteLine(" \"default_dlc_status\": \"unlocked\",");
if (overrideCatalogItems.Count > 0)
{
writer.WriteLine(" \"override\": [");
writer.WriteLine(" \"override_dlc_status\": {");
KeyValuePair<string, SelectionDLC> lastOverrideCatalogItem = overrideCatalogItems.Last();
foreach (KeyValuePair<string, SelectionDLC> pair in overrideCatalogItems)
{
SelectionDLC selectionDlc = pair.Value;
writer.WriteLine($" \"{selectionDlc.Id}\"{(pair.Equals(lastOverrideCatalogItem) ? "" : ",")}");
writer.WriteLine($" \"{selectionDlc.Id}\": \"locked\"{(pair.Equals(lastOverrideCatalogItem) ? "" : ",")}");
installForm?.UpdateUser(
$"Added locked catalog item to ScreamAPI.json with id {selectionDlc.Id} ({selectionDlc.Name})",
LogTextBox.Action,
false);
}
writer.WriteLine(" ]");
writer.WriteLine(" },");
}
else
writer.WriteLine(" \"override\": []");
writer.WriteLine(" \"override_dlc_status\": {},");
writer.WriteLine(" },");
writer.WriteLine(" \"entitlements\": {");
if (injectedEntitlements.Count > 0)
writer.WriteLine(" \"extra_graphql_endpoints\": [],");
writer.WriteLine(" \"extra_entitlements\": {}");
/*if (injectedEntitlements.Count > 0)
{
writer.WriteLine(" \"unlock_all\": false,");
writer.WriteLine(" \"auto_inject\": false,");
writer.WriteLine(" \"default_dlc_status\": original,");
writer.WriteLine(" \"inject\": [");
KeyValuePair<string, SelectionDLC> lastEntitlement = injectedEntitlements.Last();
foreach (KeyValuePair<string, SelectionDLC> pair in injectedEntitlements)
@@ -129,7 +131,7 @@ internal static class ScreamAPI
writer.WriteLine(" \"inject\": []");
}
writer.WriteLine(" }");
writer.WriteLine(" }");*/
writer.WriteLine("}");
}
@@ -137,7 +139,7 @@ internal static class ScreamAPI
=> await Task.Run(() =>
{
directory.GetScreamApiComponents(out string api32, out string api32_o, out string api64, out string api64_o,
out string config, out string log);
out string old_config, out string config, out string old_log, out string log);
if (api32_o.FileExists())
{
if (api32.FileExists())
@@ -184,7 +186,7 @@ internal static class ScreamAPI
=> await Task.Run(() =>
{
directory.GetScreamApiComponents(out string api32, out string api32_o, out string api64, out string api64_o,
out _, out _);
out _, out _, out _, out _);
if (api32.FileExists() && !api32_o.FileExists())
{
api32.MoveFile(api32_o!, true);
@@ -221,13 +223,15 @@ internal static class ScreamAPI
[
"069A57B1834A960193D2AD6B96926D70", // ScreamAPI v3.0.0
"E2FB3A4A9583FDC215832E5F935E4440", // ScreamAPI v3.0.1
"8B4B30AFAE8D7B06413EE2F2266B20DB" // ScreamAPI v4.0.0-rc01
"8B4B30AFAE8D7B06413EE2F2266B20DB", // ScreamAPI v4.0.0-rc01
"F2C1A6B3EF73ED14E810851DBF418453" // ScreamAPI v4.0.0
],
[ResourceIdentifier.EpicOnlineServices64] =
[
"0D62E57139F1A64F807A9934946A9474", // ScreamAPI v3.0.0
"3875C7B735EE80C23239CC4749FDCBE6", // ScreamAPI v3.0.1
"CBC89E2221713B0D4482F91282030A88" // ScreamAPI v4.0.0-rc01
"CBC89E2221713B0D4482F91282030A88", // ScreamAPI v4.0.0-rc01
"2F98D62283AA024CBD756921B9533489" // ScreamAPI v4.0.0
]
};
}
+67 -6
View File
@@ -12,6 +12,11 @@ namespace CreamInstaller.Resources;
internal static class SmokeAPI
{
internal static readonly List<string> ProxyDLLs = ["winmm", "winhttp", "version"];
internal static IEnumerable<string> GetSmokeApiProxies(this string directory)
=> from proxy in ProxyDLLs select directory + @"\" + proxy + ".dll";
internal static void GetSmokeApiComponents(this string directory, out string api32, out string api32_o,
out string api64, out string api64_o,
out string old_config, out string config, out string old_log, out string log, out string cache)
@@ -88,9 +93,10 @@ internal static class SmokeAPI
InstallForm installForm = null)
{
writer.WriteLine("{");
writer.WriteLine(" \"$version\": 2,");
/*writer.WriteLine(" \"$schema\": \"https://raw.githubusercontent.com/acidicoala/SmokeAPI/refs/tags/v3.1.5/res/SmokeAPI.schema.json\",");*/
writer.WriteLine(" \"$version\": 4,");
writer.WriteLine(" \"logging\": false,");
writer.WriteLine(" \"unlock_family_sharing\": true,");
writer.WriteLine(" \"log_steam_http\": false,");
writer.WriteLine(" \"default_app_status\": \"unlocked\",");
writer.WriteLine(" \"override_app_status\": {},");
if (overrideDlc.Count > 0)
@@ -168,9 +174,8 @@ internal static class SmokeAPI
writer.WriteLine(" },");
}
else
writer.WriteLine(" \"extra_dlcs\": {},");
writer.WriteLine(" \"extra_dlcs\": {}");
writer.WriteLine(" \"store_config\": null");
writer.WriteLine("}");
}
@@ -295,6 +300,60 @@ internal static class SmokeAPI
CheckConfig(directory, selection, installForm);
});
internal static async Task ProxyUninstall(string directory, InstallForm installForm = null,
bool deleteOthers = true)
=> await Task.Run(() =>
{
foreach (string proxy in directory.GetSmokeApiProxies().Where(proxy =>
proxy.FileExists() && (proxy.IsResourceFile(ResourceIdentifier.Steamworks32) ||
proxy.IsResourceFile(ResourceIdentifier.Steamworks64))))
{
proxy.DeleteFile(true);
installForm?.UpdateUser($"Deleted SmokeAPI: {Path.GetFileName(proxy)}", LogTextBox.Action, false);
}
if (!deleteOthers)
return;
directory.GetSmokeApiComponents(out _, out _, out _, out _, out string old_config, out string config, out _,
out _, out _);
if (config.FileExists())
{
config.DeleteFile();
installForm?.UpdateUser($"Deleted configuration: {Path.GetFileName(config)}", LogTextBox.Action, false);
}
});
internal static async Task ProxyInstall(string directory, BinaryType binaryType, Selection selection,
InstallForm installForm = null, bool generateConfig = true)
=> await Task.Run(async () =>
{
await Koaloader.Uninstall(directory, selection.RootDirectory, installForm);
string proxy = selection.Proxy ?? Selection.DefaultProxy;
string path = directory + @"\" + proxy + ".dll";
foreach (string _path in directory.GetSmokeApiProxies().Where(p =>
p != path && p.FileExists() && (p.IsResourceFile(ResourceIdentifier.Steamworks32) ||
p.IsResourceFile(ResourceIdentifier.Steamworks64))))
{
_path.DeleteFile(true);
installForm?.UpdateUser($"Deleted SmokeAPI: {Path.GetFileName(_path)}", LogTextBox.Action, false);
}
if (path.FileExists() && !path.IsResourceFile(ResourceIdentifier.Steamworks32) &&
!path.IsResourceFile(ResourceIdentifier.Steamworks64))
throw new CustomMessageException("A non-SmokeAPI DLL named " + proxy +
".dll already exists in this directory!");
(binaryType == BinaryType.BIT32 ? "SmokeAPI.steam_api.dll" : "SmokeAPI.steam_api64.dll")
.WriteManifestResource(path);
installForm?.UpdateUser(
$"Wrote {(binaryType == BinaryType.BIT32 ? "32-bit" : "64-bit")} SmokeAPI: {Path.GetFileName(path)}",
LogTextBox.Action,
false);
if (generateConfig)
CheckConfig(directory, selection, installForm);
});
internal static readonly Dictionary<ResourceIdentifier, HashSet<string>> ResourceMD5s = new()
{
[ResourceIdentifier.Steamworks32] =
@@ -310,7 +369,8 @@ internal static class SmokeAPI
"C8E796DDD74F2C28996EE3F41938565C", // SmokeAPI v2.0.2
"8B075C6B272A172A014D5C9E60F13DF2", // SmokeAPI v2.0.3
"A3873569DECAD08962C46E88352E6DB1", // SmokeAPI v2.0.4
"4A1A823E5CF4FB861DD6BA94539D29C4" // SmokeAPI v2.0.5
"4A1A823E5CF4FB861DD6BA94539D29C4", // SmokeAPI v2.0.5
"EC153C0CCE476AFFB2458575930F11E6" // SmokeAPI v3.1.5
],
[ResourceIdentifier.Steamworks64] =
[
@@ -325,7 +385,8 @@ internal static class SmokeAPI
"CF9DF2E2EBA002DB98FE37FB1FB08FA8", // SmokeAPI v2.0.2
"E4DC2AF2B8B77A0C9BF9BFBBAEA11CF7", // SmokeAPI v2.0.3
"C0DDB49C9BFD3E05CBC1C61D117E93F9", // SmokeAPI v2.0.4
"F7C3064D5E3C892B168F504C21AC4923" // SmokeAPI v2.0.5
"F7C3064D5E3C892B168F504C21AC4923", // SmokeAPI v2.0.5
"5A6712770EC7CE589252706245E62C72" // SmokeAPI v3.1.5
]
};
}
Binary file not shown.
Binary file not shown.
+2
View File
@@ -45,6 +45,8 @@ internal sealed class Selection : IEquatable<Selection>
{
if (!Program.UseSmokeAPI && Platform is Platform.Steam or Platform.Paradox)
return CreamAPI.ProxyDLLs;
if (Program.UseSmokeAPI && Platform is Platform.Steam or Platform.Paradox)
return SmokeAPI.ProxyDLLs;
return EmbeddedResources.Where(r => r.StartsWith("Koaloader", StringComparison.Ordinal)).Select(p =>
{
p.GetProxyInfoFromIdentifier(out string proxyName, out _);
+1
View File
@@ -3,6 +3,7 @@ $Array64 = [System.Text.StringBuilder]::new().AppendLine('[')
function Write-Hash([System.IO.FileInfo] $File, [string] $Version) {
$Hash = (Get-FileHash $File -Algorithm MD5).Hash
$Value = "`t`"$Hash`", // CreamAPI $Version"
$Value = "`t`"$Hash`", // SmokeAPI $Version"
if ($File.Name.Contains('64')) {
$Array64.AppendLine($Value) | Out-Null
} else {
+11 -11
View File
@@ -1,10 +1,10 @@
### CreamInstaller: Automatic DLC Unlocker Installer & Configuration Generator
### [Forked] CreamInstaller: Automatic DLC Unlocker Installer & Configuration Generator
![Program Preview Image](https://raw.githubusercontent.com/FroggMaster/CreamInstaller/main/preview.png)
![Program Preview Image](https://raw.githubusercontent.com/HvTcCore/CreamInstaller/main/preview.png)
###### **NOTE:** This is simply a preview image; this is not a list of supported games nor configurations!
##### The program utilizes the latest version of [CreamAPI](https://cs.rin.ru/forum/viewtopic.php?f=29&t=70576) by [deadmau5](https://cs.rin.ru/forum/viewtopic.php?f=29&t=70576). It also utilizes the latest versions of [Koaloader](https://github.com/acidicoala/Koaloader), ~~[SmokeAPI](https://github.com/acidicoala/SmokeAPI)~~, [ScreamAPI](https://github.com/acidicoala/ScreamAPI), [Uplay R1 Unlocker](https://github.com/acidicoala/UplayR1Unlocker) and [Uplay R2 Unlocker](https://github.com/acidicoala/UplayR2Unlocker), all by [acidicoala](https://github.com/acidicoala). All unlockers are downloaded and embedded into the program itself; no further downloads necessary on your part!
##### The program utilizes the latest version of [CreamAPI](https://cs.rin.ru/forum/viewtopic.php?f=29&t=70576) by [deadmau5](https://cs.rin.ru/forum/viewtopic.php?f=29&t=70576). It also utilizes the latest versions of [SmokeAPI](https://github.com/acidicoala/SmokeAPI), [Koaloader](https://github.com/acidicoala/Koaloader), [ScreamAPI](https://github.com/acidicoala/ScreamAPI), [Uplay R1 Unlocker](https://github.com/acidicoala/UplayR1Unlocker) and [Uplay R2 Unlocker](https://github.com/acidicoala/UplayR2Unlocker), all by [acidicoala](https://github.com/acidicoala). All unlockers are downloaded and embedded into the program itself; no further downloads necessary on your part!
---
#### Description:
Automatically finds all installed Steam, Epic and Ubisoft games with their respective DLC-related DLL locations on the user's computer,
@@ -29,7 +29,7 @@ games and DLCs the user selects; however, through the use of **right-click conte
---
#### Installation:
1. Click [here](https://github.com/FroggMaster/CreamInstaller/releases/latest/download/CreamInstaller.zip) to download the latest release from [GitHub](https://github.com/FroggMaster/CreamInstaller).
1. Click [here](https://github.com/HvTcCore/CreamInstaller/releases/latest/download/CreamInstaller.zip) to download the latest release from [GitHub](https://github.com/HvtcCore/CreamInstaller).
2. Extract the executable from the ZIP file to anywhere on your computer you want. *It's completely self-contained.*
If the program doesn't seem to launch, try downloading and installing [.NET Desktop Runtime 8.0.7](https://download.visualstudio.microsoft.com/download/pr/bb581716-4cca-466e-9857-512e2371734b/5fe261422a7305171866fd7812d0976f/windowsdesktop-runtime-8.0.7-win-x64.exe) and restarting your computer. Note that the program currently only supports Windows 10+ 64-bit machines as seen [here](https://github.com/dotnet/core/blob/main/release-notes/8.0/supported-os.md).
@@ -52,23 +52,23 @@ If the program doesn't seem to launch, try downloading and installing [.NET Desk
#### FAQ / Common Issues:
**Q:** The program is not launching.
**A:** First and foremost, note that the program currently only supports Windows 10+ 64-bit machines as seen [here](https://github.com/dotnet/core/blob/main/release-notes/8.0/supported-os.md). If that does not apply to you, then make sure you've extracted the executable from the ZIP file before you've launched it, resolved your anti-virus, and have tried downloading the .NET Desktop Runtime mentioned under [installation instructions](https://github.com/FroggMaster/CreamInstaller#installation) above and restarting your computer. If none of the above work, then I simply cannot do anything about it, I do not control .NET. Either your system is not supported by the current version of .NET, or something is wrong/corrupted with your system.
**A:** First and foremost, note that the program currently only supports Windows 10+ 64-bit machines as seen [here](https://github.com/dotnet/core/blob/main/release-notes/8.0/supported-os.md). If that does not apply to you, then make sure you've extracted the executable from the ZIP file before you've launched it, resolved your anti-virus, and have tried downloading the .NET Desktop Runtime mentioned under [installation instructions](https://github.com/HvTcCore/CreamInstaller#installation) above and restarting your computer. If none of the above work, then I simply cannot do anything about it, I do not control .NET. Either your system is not supported by the current version of .NET, or something is wrong/corrupted with your system.
**Q:** The game I installed the unlocker(s) to is not working/the DLCs are not unlocked.
**A:** Make sure you've read the note under [Usage](https://github.com/FroggMaster/CreamInstaller#usage) above! Assuming the program functioned as it was supposed to by properly installing DLC unlockers to your chosen games, this is not an issue I can do anything about and it's entirely up to you to seek the appropriate resources to fix it yourself (hint: https://cs.rin.ru/forum/viewforum.php?f=10).
**A:** Make sure you've read the note under [Usage](https://github.com/HvTcCore/CreamInstaller#usage) above! Assuming the program functioned as it was supposed to by properly installing DLC unlockers to your chosen games, this is not an issue I can do anything about and it's entirely up to you to seek the appropriate resources to fix it yourself (hint: https://cs.rin.ru/forum/viewforum.php?f=10).
**Q:** The program and/or files installed by the program are detected as a virus/trojan/malware.
**A:** The "issue" of the program's outputted Koaloader DLLs being detected as false positives such as Mamson.A!ac, Phonzy.A!ml, Wacatac.H!ml, Malgent!MSR, Tiggre!rfn, and many many others, has already been posted and explained dozens of times now in many different manners... please do not post it again, you will just be ignored; instead, refer to the explanations within issue #40 and its linked issues: https://github.com/FroggMaster/CreamInstaller/issues/40.
**A:** The "issue" of the program's outputted Koaloader DLLs being detected as false positives such as Mamson.A!ac, Phonzy.A!ml, Wacatac.H!ml, Malgent!MSR, Tiggre!rfn, and many many others, has already been posted and explained dozens of times now in many different manners... please do not post it again, you will just be ignored; instead, refer to the explanations within issue #40 and its linked issues: https://github.com/HvTcCore/CreamInstaller/issues/40.
---
##### Bugs/Crashes/Issues:
For reliable and quick assistance, all bugs, crashes and other issues should be referred to the [GitHub Issues](https://github.com/FroggMaster/CreamInstaller/issues) page!
For reliable and quick assistance, all bugs, crashes and other issues should be referred to the [GitHub Issues](https://github.com/HvTcCore/CreamInstaller/issues) page!
##### **HOWEVER**: Please read the [FAQ entry](https://github.com/FroggMaster/CreamInstaller#faq--common-issues) above and/or [template issue](https://github.com/FroggMaster/CreamInstaller/issues/new/choose) corresponding to your problem should one exist! Also, note that the [GitHub Issues](https://github.com/FroggMaster/CreamInstaller/issues) page is not your personal assistance hotline, rather it is for genuine bugs/crashes/issues with the program itself. If you post an issue which is off-topic or has already been explained within the FAQ, template issues, and/or within this text in general, I will just close it and you will be ignored.
##### **HOWEVER**: Please read the [FAQ entry](https://github.com/HvTcCore/CreamInstaller#faq--common-issues) above and/or [template issue](https://github.com/HvTcCore/CreamInstaller/issues/new/choose) corresponding to your problem should one exist! Also, note that the [GitHub Issues](https://github.com/HvTcCore/CreamInstaller/issues) page is not your personal assistance hotline, rather it is for genuine bugs/crashes/issues with the program itself. If you post an issue which is off-topic or has already been explained within the FAQ, template issues, and/or within this text in general, I will just close it and you will be ignored.
---
##### More Information:
* SteamCMD installation and appinfo cache can be found at **C:\ProgramData\CreamInstaller**.
* The program automatically and very quickly updates from [GitHub](https://github.com/FroggMaster/CreamInstaller) by choice of the user through a dialog on startup.
* The program source and other information can be found on [GitHub](https://github.com/FroggMaster/CreamInstaller).
* The program automatically and very quickly updates from [GitHub](https://github.com/HvTcCore/CreamInstaller) by choice of the user through a dialog on startup.
* The program source and other information can be found on [GitHub](https://github.com/HvTcCore/CreamInstaller).
* Credit to [Mattahan](https://www.mattahan.com) for the program icon.