1
0
mirror of https://github.com/FunkyFr3sh/cnc-ddraw.git synced 2025-03-22 16:46:16 +01:00
cnc-ddraw/src/settings.c
2020-01-23 08:58:22 +01:00

486 lines
16 KiB
C

#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <stdio.h>
#include <d3d9.h>
#include "main.h"
#include "opengl.h"
#include "render_d3d9.h"
#include "hook.h"
static char SettingsIniPath[MAX_PATH];
static char ProcessFileName[96];
static BOOL GetBool(LPCSTR key, BOOL defaultValue);
static int GetInt(LPCSTR key, int defaultValue);
static DWORD GetString(LPCSTR key, LPCSTR defaultValue, LPSTR outString, DWORD outSize);
static void CreateSettingsIni();
void Settings_Load()
{
//set up settings ini
char cwd[MAX_PATH];
char tmp[256];
GetCurrentDirectoryA(sizeof(cwd), cwd);
_snprintf(SettingsIniPath, sizeof(SettingsIniPath), "%s\\ddraw.ini", cwd);
if (GetFileAttributes(SettingsIniPath) == INVALID_FILE_ATTRIBUTES)
CreateSettingsIni();
//get process filename
char ProcessFilePath[MAX_PATH] = { 0 };
GetModuleFileNameA(NULL, ProcessFilePath, MAX_PATH);
_splitpath(ProcessFilePath, NULL, NULL, ProcessFileName, NULL);
//load settings from ini
ddraw->windowed = GetBool("windowed", FALSE);
ddraw->border = GetBool("border", TRUE);
ddraw->boxing = GetBool("boxing", FALSE);
ddraw->maintas = GetBool("maintas", FALSE);
ddraw->adjmouse = GetBool("adjmouse", FALSE);
ddraw->devmode = GetBool("devmode", FALSE);
ddraw->vsync = GetBool("vsync", FALSE);
ddraw->noactivateapp = GetBool("noactivateapp", FALSE);
ddraw->vhack = GetBool("vhack", FALSE);
ddraw->accurateTimers = GetBool("accuratetimers", FALSE);
ddraw->resizable = GetBool("resizable", TRUE);
WindowRect.right = GetInt("width", 0);
WindowRect.bottom = GetInt("height", 0);
WindowRect.left = GetInt("posX", -32000);
WindowRect.top = GetInt("posY", -32000);
#ifndef _DEBUG
HookingMethod = GetInt("hook", 1);
#endif
ddraw->render.maxfps = GetInt("maxfps", 125);
if (ddraw->render.maxfps)
ddraw->render.forcefps = GetBool("forcefps", FALSE);
if (ddraw->accurateTimers || ddraw->vsync)
ddraw->fpsLimiter.hTimer = CreateWaitableTimer(NULL, TRUE, NULL);
//can't fully set it up here due to missing ddraw->mode.dmDisplayFrequency
int maxTicks = GetInt("maxgameticks", 0);
if (maxTicks > 0 && maxTicks <= 1000)
{
if (ddraw->accurateTimers)
ddraw->ticksLimiter.hTimer = CreateWaitableTimer(NULL, TRUE, NULL);
float len = 1000.0f / maxTicks;
ddraw->ticksLimiter.tickLengthNs = len * 10000;
ddraw->ticksLimiter.ticklength = len + 0.5f;
}
//always using 60 fps for flip...
if (ddraw->accurateTimers)
ddraw->flipLimiter.hTimer = CreateWaitableTimer(NULL, TRUE, NULL);
float flipLen = 1000.0f / 60;
ddraw->flipLimiter.tickLengthNs = flipLen * 10000;
ddraw->flipLimiter.ticklength = flipLen + 0.5f;
if ((ddraw->fullscreen = GetBool("fullscreen", FALSE)))
WindowRect.left = WindowRect.top = -32000;
if (!(ddraw->handlemouse = GetBool("handlemouse", TRUE)))
ddraw->adjmouse = TRUE;
if (GetBool("singlecpu", TRUE))
{
SetProcessAffinityMask(GetCurrentProcess(), 1);
}
else
{
DWORD systemAffinity;
DWORD procAffinity;
HANDLE proc = GetCurrentProcess();
if (GetProcessAffinityMask(proc, &procAffinity, &systemAffinity))
SetProcessAffinityMask(proc, systemAffinity);
}
ddraw->render.bpp = GetInt("bpp", 32);
if (ddraw->render.bpp != 16 && ddraw->render.bpp != 24 && ddraw->render.bpp != 32)
ddraw->render.bpp = 0;
// to do: read .glslp config file instead of the shader and apply the correct settings
GetString("shader", "", ddraw->shader, sizeof(ddraw->shader));
GetString("renderer", "auto", tmp, sizeof(tmp));
printf("Using %s renderer\n", tmp);
if (tolower(tmp[0]) == 's' || tolower(tmp[0]) == 'g') //gdi
{
ddraw->renderer = render_soft_main;
}
else if (tolower(tmp[0]) == 'd') //direct3d9
{
ddraw->renderer = render_d3d9_main;
}
else if (tolower(tmp[0]) == 'o') //opengl
{
if (OpenGL_LoadDll())
{
ddraw->renderer = render_main;
}
else
{
ShowDriverWarning = TRUE;
ddraw->renderer = render_soft_main;
}
}
else //auto
{
LPDIRECT3D9 d3d = NULL;
// Windows = Direct3D 9, Wine = OpenGL
if (!ddraw->wine && (Direct3D9_hModule = LoadLibrary("d3d9.dll")))
{
IDirect3D9 *(WINAPI *D3DCreate9)(UINT) =
(IDirect3D9 *(WINAPI *)(UINT))GetProcAddress(Direct3D9_hModule, "Direct3DCreate9");
if (D3DCreate9 && (d3d = D3DCreate9(D3D_SDK_VERSION)))
IDirect3D9_Release(d3d);
}
if (d3d)
{
ddraw->renderer = render_d3d9_main;
}
else if (OpenGL_LoadDll())
{
ddraw->renderer = render_main;
}
else
{
ShowDriverWarning = TRUE;
ddraw->renderer = render_soft_main;
}
}
}
void Settings_Save(RECT *lpRect, int windowState)
{
char buf[16];
if (lpRect->right)
{
sprintf(buf, "%ld", lpRect->right);
WritePrivateProfileString(ProcessFileName, "width", buf, SettingsIniPath);
}
if (lpRect->bottom)
{
sprintf(buf, "%ld", lpRect->bottom);
WritePrivateProfileString(ProcessFileName, "height", buf, SettingsIniPath);
}
if (lpRect->left != -32000)
{
sprintf(buf, "%ld", lpRect->left);
WritePrivateProfileString(ProcessFileName, "posX", buf, SettingsIniPath);
}
if (lpRect->top != -32000)
{
sprintf(buf, "%ld", lpRect->top);
WritePrivateProfileString(ProcessFileName, "posY", buf, SettingsIniPath);
}
if (windowState != -1)
{
WritePrivateProfileString(ProcessFileName, "windowed", windowState ? "true" : "false", SettingsIniPath);
}
}
static void CreateSettingsIni()
{
FILE *fh = fopen(SettingsIniPath, "w");
if (fh)
{
fputs(
"; cnc-ddraw - https://github.com/CnCNet/cnc-ddraw - https://cncnet.org\n"
"\n"
"[ddraw]\n"
"; ### Optional settings ###\n"
"; Use the following settings to adjust the look and feel to your liking\n"
"\n"
"\n"
"; Stretch to custom resolution, 0 = defaults to the size game requests\n"
"width=0\n"
"height=0\n"
"\n"
"; Override the width/height settings shown above and always stretch to fullscreen\n"
"; Note: Can be combined with 'windowed=true' to get windowed-fullscreen aka borderless mode\n"
"fullscreen=false\n"
"\n"
"; Run in windowed mode rather than going fullscreen\n"
"windowed=false\n"
"\n"
"; Maintain aspect ratio - (Requires 'handlemouse=true')\n"
"maintas=false\n"
"\n"
"; Windowboxing / Integer Scaling - (Requires 'handlemouse=true')\n"
"boxing=false\n"
"\n"
"; Real rendering rate, -1 = screen rate, 0 = unlimited, n = cap\n"
"; Note: Does not have an impact on the game speed, to limit your game speed use 'maxgameticks='\n"
"maxfps=125\n"
"\n"
"; Vertical synchronization, enable if you get tearing - (Requires 'renderer=auto/opengl/direct3d9')\n"
"vsync=false\n"
"\n"
"; Automatic mouse sensitivity scaling - (Requires 'handlemouse=true')\n"
"; Note: Only works if stretching is enabled. Sensitivity will be adjusted according to the size of the window\n"
"adjmouse=false\n"
"\n"
"; Preliminary libretro shader support - (Requires 'renderer=opengl') https://github.com/libretro/glsl-shaders\n"
"shader=Shaders\\bilinear.glsl\n"
"\n"
"; Window position, -32000 = center to screen\n"
"posX=-32000\n"
"posY=-32000\n"
"\n"
"; Renderer, possible values: auto, opengl, gdi, direct3d9 (auto = try direct3d9/opengl, fallback = gdi)\n"
"renderer=auto\n"
"\n"
"; Developer mode (don't lock the cursor)\n"
"devmode=false\n"
"\n"
"; Show window borders in windowed mode\n"
"border=true\n"
"\n"
"; Bits per pixel, possible values: 16, 24 and 32, 0 = auto\n"
"bpp=0\n"
"\n"
"; Enable C&C video resize hack - Stretches C&C cutscenes to fullscreen\n"
"vhack=false\n"
"\n"
"\n"
"\n"
"; ### Compatibility settings ###\n"
"; Use the following settings in case there are any issues with the game\n"
"\n"
"\n"
"; Hide WM_ACTIVATEAPP messages to prevent problems on alt+tab\n"
"noactivateapp=false\n"
"\n"
"; Max game ticks per second, possible values: 0-1000\n"
"; Note: Can be used to slow down a too fast running game, fix flickering or too fast animations\n"
"maxgameticks=0\n"
"\n"
"; Gives cnc-ddraw full control over the mouse cursor (required for adjmouse/boxing/maintas)\n"
"; Note: This option only works for games that draw their own cursor and it must be disabled for all other games\n"
"handlemouse=true\n"
"\n"
"; Use Waitable Timer Objects rather than timeGetTime+Sleep to limit FPS/Ticks/Flip\n"
"; Note: To workaround tearing/stuttering problems, set maxfps 1 lower than screen refresh rate (59 for flip games)\n"
"accuratetimers=false\n"
"\n"
"; Force CPU0 affinity, avoids crashes/freezing, *might* have a performance impact\n"
"singlecpu=true\n"
"\n"
"; Windows API Hooking, Possible values: 0 = disabled, 1 = IAT Hooking, 2 = Microsoft Detours\n"
"; Note: Can be used to fix issues related to new features added by cnc-ddraw such as windowed mode or stretching\n"
"hook=1\n"
"\n"
"; Force consistent FPS (Requires 'maxfps=' to be set to a value other than 0)\n"
"; Note: Fixes flickering cursor issues in C&C games\n"
"forcefps=false\n"
"\n"
"\n"
"\n"
"; ### Game specific settings ###\n"
"; The following settings override all settings shown above, section name = executable name\n"
"\n"
"\n"
"; Carmageddon\n"
"[CARMA95]\n"
"renderer=opengl\n"
"noactivateapp=true\n"
"maxgameticks=30\n"
"\n"
"; Command & Conquer Gold\n"
"[C&C95]\n"
"maxgameticks=120\n"
"maxfps=60\n"
"forcefps=true\n"
"\n"
"; Command & Conquer: Red Alert\n"
"[ra95]\n"
"maxgameticks=120\n"
"maxfps=60\n"
"forcefps=true\n"
"\n"
"; Command & Conquer: Red Alert\n"
"[ra95p]\n"
"maxgameticks=120\n"
"maxfps=60\n"
"forcefps=true\n"
"\n"
"; Age of Empires\n"
"[empires]\n"
"handlemouse=false\n"
"\n"
"; Age of Empires: The Rise of Rome\n"
"[empiresx]\n"
"handlemouse=false\n"
"\n"
"; Age of Empires II\n"
"[EMPIRES2]\n"
"handlemouse=false\n"
"\n"
"; Age of Empires II: The Conquerors\n"
"[age2_x1]\n"
"handlemouse=false\n"
"\n"
"; Outlaws\n"
"[olwin]\n"
"noactivateapp=true\n"
"maxgameticks=60\n"
"hook=2\n"
"handlemouse=false\n"
"renderer=gdi\n"
"\n"
"; Dark Reign: The Future of War\n"
"[DKReign]\n"
"maxgameticks=60\n"
"\n"
"; Star Wars: Galactic Battlegrounds\n"
"[battlegrounds]\n"
"handlemouse=false\n"
"\n"
"; Star Wars: Galactic Battlegrounds: Clone Campaigns\n"
"[battlegrounds_x1]\n"
"handlemouse=false\n"
"\n"
"; Carmageddon 2\n"
"[Carma2_SW]\n"
"renderer=opengl\n"
"noactivateapp=true\n"
"maxgameticks=60\n"
"\n"
"; Atomic Bomberman\n"
"[BM]\n"
"maxgameticks=60\n"
"\n"
"; Dune 2000\n"
"[dune2000]\n"
"maxfps=59\n"
"accuratetimers=true\n"
"\n"
"; Dune 2000 - CnCNet\n"
"[dune2000-spawn]\n"
"maxfps=59\n"
"accuratetimers=true\n"
"\n"
"; Command & Conquer: Tiberian Sun / Command & Conquer: Red Alert 2\n"
"[game]\n"
"checkfile=.\\blowfish.dll\n"
"noactivateapp=true\n"
"handlemouse=false\n"
"maxfps=60\n"
"forcefps=true\n"
"\n"
"; Command & Conquer: Tiberian Sun Demo\n"
"[SUN]\n"
"noactivateapp=true\n"
"handlemouse=false\n"
"maxfps=60\n"
"forcefps=true\n"
"\n"
"; Command & Conquer: Tiberian Sun - CnCNet\n"
"[ts-spawn]\n"
"noactivateapp=true\n"
"handlemouse=false\n"
"maxfps=60\n"
"forcefps=true\n"
"\n"
"; Command & Conquer: Red Alert 2 - XWIS\n"
"[ra2]\n"
"noactivateapp=true\n"
"handlemouse=false\n"
"maxfps=60\n"
"forcefps=true\n"
"\n"
"; Command & Conquer: Red Alert 2 - XWIS\n"
"[Red Alert 2]\n"
"noactivateapp=true\n"
"handlemouse=false\n"
"maxfps=60\n"
"forcefps=true\n"
"\n"
"; Command & Conquer: Red Alert 2: Yuri's Revenge\n"
"[gamemd]\n"
"noactivateapp=true\n"
"handlemouse=false\n"
"maxfps=60\n"
"forcefps=true\n"
"\n"
"; Command & Conquer: Red Alert 2: Yuri's Revenge - ?ModExe?\n"
"[ra2md]\n"
"noactivateapp=true\n"
"handlemouse=false\n"
"maxfps=60\n"
"forcefps=true\n"
"\n"
"; Command & Conquer: Red Alert 2: Yuri's Revenge - CnCNet\n"
"[gamemd-spawn]\n"
"noactivateapp=true\n"
"handlemouse=false\n"
"maxfps=60\n"
"forcefps=true\n"
"\n"
"; Command & Conquer: Red Alert 2: Yuri's Revenge - XWIS\n"
"[Yuri's Revenge]\n"
"noactivateapp=true\n"
"handlemouse=false\n"
"maxfps=60\n"
"forcefps=true\n"
"\n"
, fh);
fclose(fh);
}
}
static DWORD GetString(LPCSTR key, LPCSTR defaultValue, LPSTR outString, DWORD outSize)
{
DWORD s = GetPrivateProfileStringA(ProcessFileName, key, "", outString, outSize, SettingsIniPath);
if (s > 0)
{
char buf[MAX_PATH] = { 0 };
if (GetPrivateProfileStringA(ProcessFileName, "checkfile", "", buf, sizeof(buf), SettingsIniPath) > 0)
{
if (GetFileAttributes(buf) != INVALID_FILE_ATTRIBUTES)
return s;
}
else
return s;
}
return GetPrivateProfileStringA("ddraw", key, defaultValue, outString, outSize, SettingsIniPath);
}
static BOOL GetBool(LPCSTR key, BOOL defaultValue)
{
char value[8];
GetString(key, defaultValue ? "Yes" : "No", value, sizeof(value));
return (_stricmp(value, "yes") == 0 || _stricmp(value, "true") == 0 || _stricmp(value, "1") == 0);
}
static int GetInt(LPCSTR key, int defaultValue)
{
char defvalue[16];
_snprintf(defvalue, sizeof(defvalue), "%d", defaultValue);
char value[16];
GetString(key, defvalue, value, sizeof(value));
return atoi(value);
}