Merge pull request #8397 from unknownbrackets/ui-tweaks

Fix backend setting getting lost with per-game configs
This commit is contained in:
Henrik Rydgård 2016-01-06 10:21:04 +01:00
commit 55c7110e2a
14 changed files with 123 additions and 117 deletions

View File

@ -20,6 +20,7 @@
#include <algorithm>
#include "base/display.h"
#include "base/functional.h"
#include "base/NativeApp.h"
#include "ext/vjson/json.h"
#include "file/ini_file.h"
@ -442,7 +443,6 @@ static ConfigSetting graphicsSettings[] = {
ReportedConfigSetting("FrameRate", &g_Config.iFpsLimit, 0, true, true),
#ifdef _WIN32
ConfigSetting("FrameSkipUnthrottle", &g_Config.bFrameSkipUnthrottle, false, true, true),
ConfigSetting("TemporaryGPUBackend", &g_Config.iTempGPUBackend, -1, false),
ConfigSetting("RestartRequired", &g_Config.bRestartRequired, false, false),
#else
ConfigSetting("FrameSkipUnthrottle", &g_Config.bFrameSkipUnthrottle, true),
@ -754,6 +754,15 @@ static ConfigSectionSettings sections[] = {
{"Upgrade", upgradeSettings},
};
static void IterateSettings(IniFile &iniFile, std::function<void(IniFile::Section *section, ConfigSetting *setting)> func) {
for (size_t i = 0; i < ARRAY_SIZE(sections); ++i) {
IniFile::Section *section = iniFile.GetOrCreateSection(sections[i].section);
for (auto setting = sections[i].settings; setting->HasMore(); ++setting) {
func(section, setting);
}
}
}
Config::Config() : bGameSpecific(false) { }
Config::~Config() { }
@ -813,12 +822,9 @@ void Config::Load(const char *iniFileName, const char *controllerIniFilename) {
// Continue anyway to initialize the config.
}
for (size_t i = 0; i < ARRAY_SIZE(sections); ++i) {
IniFile::Section *section = iniFile.GetOrCreateSection(sections[i].section);
for (auto setting = sections[i].settings; setting->HasMore(); ++setting) {
setting->Get(section);
}
}
IterateSettings(iniFile, [](IniFile::Section *section, ConfigSetting *setting) {
setting->Get(section);
});
iRunCount++;
if (!File::Exists(currentDirectory))
@ -924,14 +930,7 @@ void Config::Load(const char *iniFileName, const char *controllerIniFilename) {
INFO_LOG(LOADER, "Loading controller config: %s", controllerIniFilename_.c_str());
bSaveSettings = true;
IniFile controllerIniFile;
if (!controllerIniFile.Load(controllerIniFilename_)) {
ERROR_LOG(LOADER, "Failed to read %s. Setting controller config to default.", controllerIniFilename_.c_str());
KeyMap::RestoreDefault();
} else {
// Continue anyway to initialize the config. It will just restore the defaults.
KeyMap::LoadFromIni(controllerIniFile);
}
LoadStandardControllerIni();
//so this is all the way down here to overwrite the controller settings
//sadly it won't benefit from all the "version conversion" going on up-above
@ -943,10 +942,6 @@ void Config::Load(const char *iniFileName, const char *controllerIniFilename) {
CleanRecent();
#ifdef _WIN32
iTempGPUBackend = iGPUBackend;
#endif
// Fix Wrong MAC address by old version by "Change MAC address"
if (sMACAddress.length() != 17)
sMACAddress = CreateRandMAC();
@ -980,14 +975,11 @@ void Config::Save() {
// Need to do this somewhere...
bFirstRun = false;
for (size_t i = 0; i < ARRAY_SIZE(sections); ++i) {
IniFile::Section *section = iniFile.GetOrCreateSection(sections[i].section);
for (auto setting = sections[i].settings; setting->HasMore(); ++setting) {
if (!bGameSpecific || !setting->perGame_){
setting->Set(section);
}
IterateSettings(iniFile, [&](IniFile::Section *section, ConfigSetting *setting) {
if (!bGameSpecific || !setting->perGame_) {
setting->Set(section);
}
}
});
IniFile::Section *recent = iniFile.GetOrCreateSection("Recent");
recent->Set("MaxRecent", iMaxRecent);
@ -1173,13 +1165,10 @@ const std::string Config::FindConfigFile(const std::string &baseFilename) {
}
void Config::RestoreDefaults() {
if (bGameSpecific)
{
if (bGameSpecific) {
deleteGameConfig(gameId_);
createGameConfig(gameId_);
}
else
{
} else {
if (File::Exists(iniFilename_))
File::Delete(iniFilename_);
recentIsos.clear();
@ -1188,25 +1177,21 @@ void Config::RestoreDefaults() {
Load();
}
bool Config::hasGameConfig(const std::string &pGameId)
{
bool Config::hasGameConfig(const std::string &pGameId) {
std::string fullIniFilePath = getGameConfigFile(pGameId);
return File::Exists(fullIniFilePath);
}
void Config::changeGameSpecific(const std::string &pGameId)
{
void Config::changeGameSpecific(const std::string &pGameId) {
Save();
gameId_ = pGameId;
bGameSpecific = !pGameId.empty();
}
bool Config::createGameConfig(const std::string &pGameId)
{
bool Config::createGameConfig(const std::string &pGameId) {
std::string fullIniFilePath = getGameConfigFile(pGameId);
if (hasGameConfig(pGameId))
{
if (hasGameConfig(pGameId)) {
return false;
}
@ -1215,26 +1200,22 @@ bool Config::createGameConfig(const std::string &pGameId)
return true;
}
bool Config::deleteGameConfig(const std::string& pGameId)
{
bool Config::deleteGameConfig(const std::string& pGameId) {
std::string fullIniFilePath = getGameConfigFile(pGameId);
File::Delete(fullIniFilePath);
return true;
}
std::string Config::getGameConfigFile(const std::string &pGameId)
{
std::string Config::getGameConfigFile(const std::string &pGameId) {
std::string iniFileName = pGameId + "_ppsspp.ini";
std::string iniFileNameFull = FindConfigFile(iniFileName);
return iniFileNameFull;
}
bool Config::saveGameConfig(const std::string &pGameId)
{
if (pGameId.empty())
{
bool Config::saveGameConfig(const std::string &pGameId) {
if (pGameId.empty()) {
return false;
}
@ -1242,14 +1223,11 @@ bool Config::saveGameConfig(const std::string &pGameId)
IniFile iniFile;
for (size_t i = 0; i < ARRAY_SIZE(sections); ++i) {
IniFile::Section *section = iniFile.GetOrCreateSection(sections[i].section);
for (auto setting = sections[i].settings; setting->HasMore(); ++setting) {
if (setting->perGame_){
setting->Set(section);
}
IterateSettings(iniFile, [](IniFile::Section *section, ConfigSetting *setting) {
if (setting->perGame_) {
setting->Set(section);
}
}
});
KeyMap::SaveToIni(iniFile);
iniFile.Save(fullIniFilePath);
@ -1257,12 +1235,10 @@ bool Config::saveGameConfig(const std::string &pGameId)
return true;
}
bool Config::loadGameConfig(const std::string &pGameId)
{
bool Config::loadGameConfig(const std::string &pGameId) {
std::string iniFileNameFull = getGameConfigFile(pGameId);
if (!hasGameConfig(pGameId))
{
if (!hasGameConfig(pGameId)) {
INFO_LOG(LOADER, "Failed to read %s. No game-specific settings found, using global defaults.", iniFileNameFull.c_str());
return false;
}
@ -1271,26 +1247,42 @@ bool Config::loadGameConfig(const std::string &pGameId)
IniFile iniFile;
iniFile.Load(iniFileNameFull);
for (size_t i = 0; i < ARRAY_SIZE(sections); ++i) {
IniFile::Section *section = iniFile.GetOrCreateSection(sections[i].section);
for (auto setting = sections[i].settings; setting->HasMore(); ++setting) {
if (setting->perGame_){
setting->Get(section);
}
IterateSettings(iniFile, [](IniFile::Section *section, ConfigSetting *setting) {
if (setting->perGame_) {
setting->Get(section);
}
}
});
KeyMap::LoadFromIni(iniFile);
return true;
}
void Config::unloadGameConfig()
{
if (bGameSpecific)
{
void Config::unloadGameConfig() {
if (bGameSpecific){
changeGameSpecific();
Load(iniFilename_.c_str(), controllerIniFilename_.c_str());
IniFile iniFile;
iniFile.Load(iniFilename_);
// Reload game specific settings back to standard.
IterateSettings(iniFile, [](IniFile::Section *section, ConfigSetting *setting) {
if (setting->perGame_) {
setting->Get(section);
}
});
LoadStandardControllerIni();
}
}
void Config::LoadStandardControllerIni() {
IniFile controllerIniFile;
if (!controllerIniFile.Load(controllerIniFilename_)) {
ERROR_LOG(LOADER, "Failed to read %s. Setting controller config to default.", controllerIniFilename_.c_str());
KeyMap::RestoreDefault();
} else {
// Continue anyway to initialize the config. It will just restore the defaults.
KeyMap::LoadFromIni(controllerIniFile);
}
}

View File

@ -45,9 +45,13 @@ enum BufferFilter {
};
// Software is not among these because it will have one of these perform the blit to display.
enum class GPUBackend {
OPENGL = 0,
DIRECT3D9 = 1,
};
enum {
GPU_BACKEND_OPENGL = 0,
GPU_BACKEND_DIRECT3D9 = 1,
GPU_BACKEND_OPENGL = GPUBackend::OPENGL,
GPU_BACKEND_DIRECT3D9 = GPUBackend::DIRECT3D9,
};
enum AudioBackendType {
@ -96,9 +100,6 @@ public:
bool bTopMost;
std::string sFont;
bool bIgnoreWindowsKey;
// Used for switching the GPU backend in GameSettingsScreen.
// Without this, PPSSPP instantly crashes if we edit iGPUBackend directly...
int iTempGPUBackend;
bool bRestartRequired;
#endif
@ -450,6 +451,9 @@ public:
bool IsPortrait() const {
return (iInternalScreenRotation == ROTATION_LOCKED_VERTICAL || iInternalScreenRotation == ROTATION_LOCKED_VERTICAL180) && iRenderingMode != 0;
}
protected:
void LoadStandardControllerIni();
private:
std::string gameId_;

View File

@ -221,10 +221,10 @@ bool TakeGameScreenshot(const char *filename, ScreenshotFormat fmt, ScreenshotTy
success = gpuDebug->GetCurrentFramebuffer(buf);
}
} else {
if (g_Config.iGPUBackend == GPU_BACKEND_OPENGL) {
if (GetGPUBackend() == GPUBackend::OPENGL) {
success = GLES_GPU::GetDisplayFramebuffer(buf);
#ifdef _WIN32
} else if (g_Config.iGPUBackend == GPU_BACKEND_DIRECT3D9) {
} else if (GetGPUBackend() == GPUBackend::DIRECT3D9) {
success = DX9::DIRECTX9_GPU::GetDisplayFramebuffer(buf);
#endif
}

View File

@ -90,6 +90,8 @@ volatile CoreState coreState = CORE_STEPPING;
volatile bool coreStatePending = false;
static volatile CPUThreadState cpuThreadState = CPU_THREAD_NOT_RUNNING;
static GPUBackend gpuBackend;
void UpdateUIState(GlobalUIState newState) {
// Never leave the EXIT state.
if (globalUIState != newState && globalUIState != UISTATE_EXIT) {
@ -102,6 +104,14 @@ GlobalUIState GetUIState() {
return globalUIState;
}
void SetGPUBackend(GPUBackend type) {
gpuBackend = type;
}
GPUBackend GetGPUBackend() {
return gpuBackend;
}
bool IsAudioInitialised() {
return audioInitialized;
}

View File

@ -48,10 +48,14 @@ enum PSPDirectories {
};
class GraphicsContext;
enum class GPUBackend;
void UpdateUIState(GlobalUIState newState);
GlobalUIState GetUIState();
void SetGPUBackend(GPUBackend type);
GPUBackend GetGPUBackend();
bool PSP_Init(const CoreParameter &coreParam, std::string *error_string);
bool PSP_InitStart(const CoreParameter &coreParam, std::string *error_string);
bool PSP_InitUpdate(std::string *error_string);

View File

@ -50,11 +50,9 @@ void CenterDisplayOutputRect(float *x, float *y, float *w, float *h, float origW
float offsetX = (g_Config.fSmallDisplayOffsetX - 0.5f) * 2.0f * frameW;
float offsetY = (g_Config.fSmallDisplayOffsetY - 0.5f) * 2.0f * frameH;
// Have to invert Y for GL
#ifdef _WIN32
if (g_Config.iGPUBackend == GPU_BACKEND_OPENGL) { offsetY = offsetY * -1.0f; }
#else
offsetY = offsetY * -1.0f;
#endif
if (GetGPUBackend() == GPUBackend::OPENGL) {
offsetY = offsetY * -1.0f;
}
float customZoom = g_Config.fSmallDisplayCustomZoom / 8.0f;
float smallDisplayW = origW * customZoom;
float smallDisplayH = origH * customZoom;

View File

@ -356,7 +356,7 @@ void SystemInfoScreen::CreateViews() {
deviceSpecs->Add(new InfoItem("Model", thin3d->GetInfoString(T3DInfo::RENDERER)));
#ifdef _WIN32
deviceSpecs->Add(new InfoItem("Driver Version", System_GetProperty(SYSPROP_GPUDRIVER_VERSION)));
if (g_Config.iGPUBackend == GPU_BACKEND_DIRECT3D9) {
if (GetGPUBackend() == GPUBackend::DIRECT3D9) {
deviceSpecs->Add(new InfoItem("D3DX Version", StringFromFormat("%d", GetD3DXVersion())));
}
#endif
@ -378,7 +378,7 @@ void SystemInfoScreen::CreateViews() {
deviceSpecs->Add(new ItemHeader("Version Information"));
std::string apiVersion;
if (g_Config.iGPUBackend == GPU_BACKEND_OPENGL) {
if (GetGPUBackend() == GPUBackend::OPENGL) {
if (gl_extensions.IsGLES) {
apiVersion = StringFromFormat("v%d.%d.%d ES", gl_extensions.ver[0], gl_extensions.ver[1], gl_extensions.ver[2]);
} else {

View File

@ -98,7 +98,7 @@ void EmuScreen::bootGame(const std::string &filename) {
CoreParameter coreParam;
coreParam.cpuCore = g_Config.bJit ? CPU_JIT : CPU_INTERPRETER;
coreParam.gpuCore = g_Config.bSoftwareRendering ? GPU_SOFTWARE : GPU_GLES;
if (g_Config.iGPUBackend == GPU_BACKEND_DIRECT3D9) {
if (GetGPUBackend() == GPUBackend::DIRECT3D9) {
coreParam.gpuCore = GPU_DIRECTX9;
}
// Preserve the existing graphics context.
@ -152,7 +152,7 @@ void EmuScreen::bootComplete() {
#endif
memset(virtKeys, 0, sizeof(virtKeys));
if (g_Config.iGPUBackend == GPU_BACKEND_OPENGL) {
if (GetGPUBackend() == GPUBackend::OPENGL) {
const char *renderer = (const char*)glGetString(GL_RENDERER);
if (strstr(renderer, "Chainfire3D") != 0) {
osm.Show(sc->T("Chainfire3DWarning", "WARNING: Chainfire3D detected, may cause problems"), 10.0f, 0xFF30a0FF, -1, true);
@ -901,7 +901,7 @@ void EmuScreen::render() {
if (invalid_)
return;
if (useBufferedRendering && g_Config.iGPUBackend == GPU_BACKEND_OPENGL)
if (useBufferedRendering && GetGPUBackend() == GPUBackend::OPENGL)
fbo_unbind();
if (!osm.IsEmpty() || g_Config.bShowDebugStats || g_Config.iShowFPSCounter || g_Config.bShowTouchControls || g_Config.bShowDeveloperMenu || g_Config.bShowAudioDebug || saveStatePreview_->GetVisibility() != UI::V_GONE || g_Config.bShowFrameProfiler) {

View File

@ -135,7 +135,7 @@ void GameSettingsScreen::CreateViews() {
graphicsSettings->Add(new ItemHeader(gr->T("Rendering Mode")));
#if defined(_WIN32)
static const char *renderingBackend[] = { "OpenGL", "Direct3D9" };
PopupMultiChoice *renderingBackendChoice = graphicsSettings->Add(new PopupMultiChoice(&g_Config.iTempGPUBackend, gr->T("Backend"), renderingBackend, GPU_BACKEND_OPENGL, ARRAY_SIZE(renderingBackend), gr->GetName(), screenManager()));
PopupMultiChoice *renderingBackendChoice = graphicsSettings->Add(new PopupMultiChoice(&g_Config.iGPUBackend, gr->T("Backend"), renderingBackend, GPU_BACKEND_OPENGL, ARRAY_SIZE(renderingBackend), gr->GetName(), screenManager()));
renderingBackendChoice->OnChoice.Handle(this, &GameSettingsScreen::OnRenderingBackend);
#endif
static const char *renderingMode[] = { "Non-Buffered Rendering", "Buffered Rendering", "Read Framebuffers To Memory (CPU)", "Read Framebuffers To Memory (GPU)"};
@ -871,13 +871,18 @@ void GlobalSettingsScreen::CreateViews() {
void GameSettingsScreen::CallbackRenderingBackend(bool yes) {
#if defined(_WIN32)
// If the user ends up deciding not to restart, set the temporary variable back to the current backend
// If the user ends up deciding not to restart, set the config back to the current backend
// so it doesn't get switched by accident.
if (yes) {
if (g_Config.iGPUBackend == (int)GPUBackend::DIRECT3D9) {
// TODO: Remove once software renderer supports D3D9.
g_Config.bSoftwareRendering = false;
}
g_Config.bRestartRequired = true;
PostMessage(MainWindow::GetHWND(), WM_CLOSE, 0, 0);
} else {
g_Config.iTempGPUBackend = g_Config.iGPUBackend;
g_Config.iGPUBackend = (int)GetGPUBackend();
}
#endif
}
@ -887,7 +892,7 @@ UI::EventReturn GameSettingsScreen::OnRenderingBackend(UI::EventParams &e) {
I18NCategory *di = GetI18NCategory("Dialog");
// It only makes sense to show the restart prompt if the backend was actually changed.
if (g_Config.iTempGPUBackend != g_Config.iGPUBackend) {
if (g_Config.iGPUBackend != (int)GetGPUBackend()) {
screenManager()->push(new PromptScreen(di->T("ChangingGPUBackends", "Changing GPU backends requires PPSSPP to restart. Restart now?"), di->T("Yes"), di->T("No"),
std::bind(&GameSettingsScreen::CallbackRenderingBackend, this, placeholder::_1)));
}

View File

@ -501,7 +501,8 @@ void NativeInit(int argc, const char *argv[],
// We do this here, instead of in NativeInitGraphics, because the display may be reset.
// When it's reset we don't want to forget all our managed things.
if (g_Config.iGPUBackend == GPU_BACKEND_OPENGL) {
SetGPUBackend((GPUBackend) g_Config.iGPUBackend);
if (GetGPUBackend() == GPUBackend::OPENGL) {
gl_lost_manager_init();
}
}
@ -689,7 +690,7 @@ void NativeRender(GraphicsContext *graphicsContext) {
// Apply the UIContext bounds as a 2D transformation matrix.
Matrix4x4 ortho;
if (g_Config.iGPUBackend == GPU_BACKEND_DIRECT3D9) {
if (GetGPUBackend() == GPUBackend::DIRECT3D9) {
ortho.setOrthoD3D(0.0f, xres, yres, 0.0f, -1.0f, 1.0f);
Matrix4x4 translation;
translation.setTranslation(Vec3(-0.5f, -0.5f, 0.0f));
@ -718,7 +719,7 @@ void NativeRender(GraphicsContext *graphicsContext) {
graphicsContext->Resize();
// TODO: Move this to new GraphicsContext objects for each backend.
#ifndef _WIN32
if (g_Config.iGPUBackend == GPU_BACKEND_OPENGL) {
if (GetGPUBackend() == GPUBackend::OPENGL) {
PSP_CoreParameter().pixelWidth = pixel_xres;
PSP_CoreParameter().pixelHeight = pixel_yres;
NativeMessageReceived("gpu resized", "");
@ -757,7 +758,7 @@ void NativeDeviceLost() {
g_gameInfoCache.Clear();
screenManager->deviceLost();
if (g_Config.iGPUBackend == GPU_BACKEND_OPENGL) {
if (GetGPUBackend() == GPUBackend::OPENGL) {
gl_lost();
}
// Should dirty EVERYTHING
@ -915,7 +916,7 @@ void NativeResized() {
}
void NativeShutdown() {
if (g_Config.iGPUBackend == GPU_BACKEND_OPENGL) {
if (GetGPUBackend() == GPUBackend::OPENGL) {
gl_lost_manager_shutdown();
}

View File

@ -270,7 +270,7 @@ namespace MainWindow {
TranslateSubMenu(menu, "Window Size", MENU_OPTIONS, SUBMENU_WINDOW_SIZE);
// Skip window size 1x-4x..
TranslateSubMenu(menu, "Backend", MENU_OPTIONS, SUBMENU_RENDERING_BACKEND);
TranslateMenuItem(menu, ID_OPTIONS_DIRECTX);
TranslateMenuItem(menu, ID_OPTIONS_DIRECT3D9);
TranslateMenuItem(menu, ID_OPTIONS_OPENGL);
TranslateSubMenu(menu, "Rendering Mode", MENU_OPTIONS, SUBMENU_RENDERING_MODE);
TranslateMenuItem(menu, ID_OPTIONS_NONBUFFEREDRENDERING);
@ -665,14 +665,16 @@ namespace MainWindow {
NativeMessageReceived("gpu clear cache", "");
break;
case ID_OPTIONS_DIRECTX:
g_Config.iTempGPUBackend = GPU_BACKEND_DIRECT3D9;
case ID_OPTIONS_DIRECT3D9:
g_Config.iGPUBackend = GPU_BACKEND_DIRECT3D9;
// TODO: Remove once software renderer supports D3D9.
g_Config.bSoftwareRendering = false;
g_Config.bRestartRequired = true;
PostMessage(MainWindow::GetHWND(), WM_CLOSE, 0, 0);
break;
case ID_OPTIONS_OPENGL:
g_Config.iTempGPUBackend = GPU_BACKEND_OPENGL;
g_Config.iGPUBackend = GPU_BACKEND_OPENGL;
g_Config.bRestartRequired = true;
PostMessage(MainWindow::GetHWND(), WM_CLOSE, 0, 0);
break;
@ -1106,13 +1108,13 @@ namespace MainWindow {
}
if (g_Config.iGPUBackend == GPU_BACKEND_DIRECT3D9) {
EnableMenuItem(menu, ID_OPTIONS_DIRECTX, MF_GRAYED);
CheckMenuItem(menu, ID_OPTIONS_DIRECTX, MF_CHECKED);
EnableMenuItem(menu, ID_OPTIONS_DIRECT3D9, MF_GRAYED);
CheckMenuItem(menu, ID_OPTIONS_DIRECT3D9, MF_CHECKED);
EnableMenuItem(menu, ID_OPTIONS_OPENGL, MF_ENABLED);
} else {
EnableMenuItem(menu, ID_OPTIONS_OPENGL, MF_GRAYED);
CheckMenuItem(menu, ID_OPTIONS_OPENGL, MF_CHECKED);
EnableMenuItem(menu, ID_OPTIONS_DIRECTX, MF_ENABLED);
EnableMenuItem(menu, ID_OPTIONS_DIRECT3D9, MF_ENABLED);
}
UpdateDynamicMenuCheckmarks(menu);

View File

@ -600,16 +600,6 @@ int WINAPI WinMain(HINSTANCE _hInstance, HINSTANCE hPrevInstance, LPSTR szCmdLin
timeEndPeriod(1);
delete host;
// Is there a safer place to do this?
// Doing this in Config::Save requires knowing if the UI state is UISTATE_EXIT,
// but that causes UnitTest to fail linking with 400 errors if System.h is included..
if (g_Config.iTempGPUBackend != g_Config.iGPUBackend) {
g_Config.iGPUBackend = g_Config.iTempGPUBackend;
// For now, turn off software rendering too, similar to the command-line.
g_Config.bSoftwareRendering = false;
}
g_Config.Save();
g_gameInfoCache.Clear();
g_gameInfoCache.Shutdown();

View File

@ -471,7 +471,7 @@ BEGIN
POPUP "Backend"
BEGIN
MENUITEM "Direct3D9" ID_OPTIONS_DIRECTX
MENUITEM "Direct3D9" ID_OPTIONS_DIRECT3D9
MENUITEM "OpenGL" ID_OPTIONS_OPENGL
END

View File

@ -316,7 +316,7 @@
#define ID_DEBUG_SAVESYMFILE 40151
#define ID_OPTIONS_BUFLINEARFILTER 40152
#define ID_OPTIONS_BUFNEARESTFILTER 40153
#define ID_OPTIONS_DIRECTX 40154
#define ID_OPTIONS_DIRECT3D9 40154
#define ID_OPTIONS_OPENGL 40155
// Dummy option to let the buffered rendering hotkey cycle through all the options.