diff --git a/app/src/main/cpp/GakumasLocalify/Hook.cpp b/app/src/main/cpp/GakumasLocalify/Hook.cpp
index 9fd86d5..068e7aa 100644
--- a/app/src/main/cpp/GakumasLocalify/Hook.cpp
+++ b/app/src/main/cpp/GakumasLocalify/Hook.cpp
@@ -433,6 +433,48 @@ namespace GakumasLocal::HookMain {
         return VLDOF_IsActive_Orig(_this);
     }
 
+    DEFINE_HOOK(void, CampusQualityManager_set_TargetFrameRate, (void* _this, float value)) {
+        // Log::InfoFmt("CampusQualityManager_set_TargetFrameRate: %f", value);
+        const auto configFps = Config::targetFrameRate;
+        CampusQualityManager_set_TargetFrameRate_Orig(_this, configFps == 0 ? value : (float)configFps);
+    }
+
+    DEFINE_HOOK(void, CampusQualityManager_ApplySetting, (void* _this, int qualitySettingsLevel, int maxBufferPixel, float renderScale, int volumeIndex)) {
+        if (Config::targetFrameRate != 0) {
+            CampusQualityManager_set_TargetFrameRate_Orig(_this, Config::targetFrameRate);
+        }
+        if (Config::useCustomeGraphicSettings) {
+            static auto SetReflectionQuality = Il2cppUtils::GetMethod("campus-submodule.Runtime.dll", "Campus.Common",
+                                                                      "CampusQualityManager", "SetReflectionQuality");
+            static auto SetLODQuality = Il2cppUtils::GetMethod("campus-submodule.Runtime.dll", "Campus.Common",
+                                                               "CampusQualityManager", "SetLODQuality");
+
+            static auto Enum_GetValues = Il2cppUtils::GetMethod("mscorlib.dll", "System", "Enum", "GetValues");
+
+            static auto QualityLevel_klass = Il2cppUtils::GetClass("campus-submodule.Runtime.dll", "", "QualityLevel");
+
+            static auto values = Enum_GetValues->Invoke<UnityResolve::UnityType::Array<int>*>(QualityLevel_klass->GetType())->ToVector();
+            if (values.empty()) {
+                values = {0x0, 0xa, 0x14, 0x1e, 0x28, 0x64};
+            }
+            if (Config::lodQualityLevel >= values.size()) Config::lodQualityLevel = values.size() - 1;
+            if (Config::reflectionQualityLevel >= values.size()) Config::reflectionQualityLevel = values.size() - 1;
+
+            SetLODQuality->Invoke<void>(_this, values[Config::lodQualityLevel]);
+            SetReflectionQuality->Invoke<void>(_this, values[Config::reflectionQualityLevel]);
+
+            qualitySettingsLevel = Config::qualitySettingsLevel;
+            maxBufferPixel = Config::maxBufferPixel;
+            renderScale = Config::renderScale;
+            volumeIndex = Config::volumeIndex;
+
+            Log::ShowToastFmt("ApplySetting\nqualityLevel: %d, maxBufferPixel: %d\nenderScale: %f, volumeIndex: %d\nLODQualityLv: %d, ReflectionLv: %d",
+                              qualitySettingsLevel, maxBufferPixel, renderScale, volumeIndex, Config::lodQualityLevel, Config::reflectionQualityLevel);
+        }
+
+        CampusQualityManager_ApplySetting_Orig(_this, qualitySettingsLevel, maxBufferPixel, renderScale, volumeIndex);
+    }
+
     void StartInjectFunctions() {
         const auto hookInstaller = Plugin::GetInstance().GetHookInstaller();
         UnityResolve::Init(xdl_open(hookInstaller->m_il2cppLibraryPath.c_str(), RTLD_NOW), UnityResolve::Mode::Il2Cpp);
@@ -488,6 +530,14 @@ namespace GakumasLocal::HookMain {
                  Il2cppUtils::GetMethodPointer("Unity.RenderPipelines.Universal.Runtime.dll", "VL.Rendering",
                                                "VLDOF", "IsActive"));
 
+        ADD_HOOK(CampusQualityManager_ApplySetting,
+                 Il2cppUtils::GetMethodPointer("campus-submodule.Runtime.dll", "Campus.Common",
+                                               "CampusQualityManager", "ApplySetting"));
+
+        ADD_HOOK(CampusQualityManager_set_TargetFrameRate,
+                 Il2cppUtils::GetMethodPointer("campus-submodule.Runtime.dll", "Campus.Common",
+                                               "CampusQualityManager", "set_TargetFrameRate"));
+
         ADD_HOOK(Internal_LogException, Il2cppUtils::il2cpp_resolve_icall(
                 "UnityEngine.DebugLogHandler::Internal_LogException(System.Exception,UnityEngine.Object)"));
         ADD_HOOK(Internal_Log, Il2cppUtils::il2cpp_resolve_icall(
diff --git a/app/src/main/cpp/GakumasLocalify/Log.cpp b/app/src/main/cpp/GakumasLocalify/Log.cpp
index d052a50..80d20ab 100644
--- a/app/src/main/cpp/GakumasLocalify/Log.cpp
+++ b/app/src/main/cpp/GakumasLocalify/Log.cpp
@@ -1,30 +1,26 @@
 #include "Log.h"
 #include <android/log.h>
+#include <Misc.h>
 #include <sstream>
 #include <string>
+#include <thread>
 
-std::string format(const char* fmt, ...) {
-    va_list args;
-    va_start(args, fmt);
-    va_list args_copy;
-    va_copy(args_copy, args);
+extern JavaVM* g_javaVM;
+extern jclass g_gakumasHookMainClass;
+extern jmethodID showToastMethodId;
 
-    // 计算格式化后的字符串长度
-    int size = vsnprintf(nullptr, 0, fmt, args_copy) + 1; // 加上额外的终止符空间
-    va_end(args_copy);
-
-    // 动态分配缓冲区
-    char* buffer = new char[size];
-
-    // 格式化字符串
-    vsnprintf(buffer, size, fmt, args);
-
-    va_end(args);
-
-    std::string result(buffer);
-    delete[] buffer; // 释放缓冲区
-    return result;
-}
+#define GetParamStringResult(name)\
+    va_list args;\
+    va_start(args, fmt);\
+    va_list args_copy;\
+    va_copy(args_copy, args);\
+    int size = vsnprintf(nullptr, 0, fmt, args_copy) + 1;\
+    va_end(args_copy);\
+    char* buffer = new char[size];\
+    vsnprintf(buffer, size, fmt, args);\
+    va_end(args);\
+    std::string name(buffer);\
+    delete[] buffer
 
 
 namespace GakumasLocal::Log {
@@ -33,26 +29,7 @@ namespace GakumasLocal::Log {
     }
 
     void LogFmt(int prio, const char* fmt, ...) {
-        va_list args;
-        va_start(args, fmt);
-        va_list args_copy;
-        va_copy(args_copy, args);
-
-        // 计算格式化后的字符串长度
-        int size = vsnprintf(nullptr, 0, fmt, args_copy) + 1; // 加上额外的终止符空间
-        va_end(args_copy);
-
-        // 动态分配缓冲区
-        char* buffer = new char[size];
-
-        // 格式化字符串
-        vsnprintf(buffer, size, fmt, args);
-
-        va_end(args);
-
-        std::string result(buffer);
-        delete[] buffer; // 释放缓冲区
-
+        GetParamStringResult(result);
         Log(prio, result.c_str());
     }
 
@@ -61,26 +38,7 @@ namespace GakumasLocal::Log {
     }
 
     void InfoFmt(const char* fmt, ...) {
-        va_list args;
-        va_start(args, fmt);
-        va_list args_copy;
-        va_copy(args_copy, args);
-
-        // 计算格式化后的字符串长度
-        int size = vsnprintf(nullptr, 0, fmt, args_copy) + 1; // 加上额外的终止符空间
-        va_end(args_copy);
-
-        // 动态分配缓冲区
-        char* buffer = new char[size];
-
-        // 格式化字符串
-        vsnprintf(buffer, size, fmt, args);
-
-        va_end(args);
-
-        std::string result(buffer);
-        delete[] buffer; // 释放缓冲区
-
+        GetParamStringResult(result);
         Info(result.c_str());
     }
 
@@ -89,26 +47,7 @@ namespace GakumasLocal::Log {
     }
 
     void ErrorFmt(const char* fmt, ...) {
-        va_list args;
-        va_start(args, fmt);
-        va_list args_copy;
-        va_copy(args_copy, args);
-
-        // 计算格式化后的字符串长度
-        int size = vsnprintf(nullptr, 0, fmt, args_copy) + 1; // 加上额外的终止符空间
-        va_end(args_copy);
-
-        // 动态分配缓冲区
-        char* buffer = new char[size];
-
-        // 格式化字符串
-        vsnprintf(buffer, size, fmt, args);
-
-        va_end(args);
-
-        std::string result(buffer);
-        delete[] buffer; // 释放缓冲区
-
+        GetParamStringResult(result);
         Error(result.c_str());
     }
 
@@ -117,50 +56,44 @@ namespace GakumasLocal::Log {
     }
 
     void DebugFmt(const char* fmt, ...) {
-        va_list args;
-        va_start(args, fmt);
-        va_list args_copy;
-        va_copy(args_copy, args);
-
-        // 计算格式化后的字符串长度
-        int size = vsnprintf(nullptr, 0, fmt, args_copy) + 1; // 加上额外的终止符空间
-        va_end(args_copy);
-
-        // 动态分配缓冲区
-        char* buffer = new char[size];
-
-        // 格式化字符串
-        vsnprintf(buffer, size, fmt, args);
-
-        va_end(args);
-
-        std::string result(buffer);
-        delete[] buffer; // 释放缓冲区
-
+        GetParamStringResult(result);
         Debug(result.c_str());
     }
 
     void LogUnityLog(int prio, const char* fmt, ...) {
-        va_list args;
-        va_start(args, fmt);
-        va_list args_copy;
-        va_copy(args_copy, args);
-
-        // 计算格式化后的字符串长度
-        int size = vsnprintf(nullptr, 0, fmt, args_copy) + 1; // 加上额外的终止符空间
-        va_end(args_copy);
-
-        // 动态分配缓冲区
-        char* buffer = new char[size];
-
-        // 格式化字符串
-        vsnprintf(buffer, size, fmt, args);
-
-        va_end(args);
-
-        std::string result(buffer);
-        delete[] buffer; // 释放缓冲区
-
+        GetParamStringResult(result);
         __android_log_write(prio, "GakumasLog", result.c_str());
     }
+
+    void ShowToast(const std::string& text) {
+        DebugFmt("Toast: %s", text.c_str());
+
+        std::thread([text](){
+            auto env = Misc::GetJNIEnv();
+            if (!env) {
+                return;
+            }
+            g_javaVM->AttachCurrentThread(&env, nullptr);
+
+            jclass& kotlinClass = g_gakumasHookMainClass;
+            if (!kotlinClass) {
+                g_javaVM->DetachCurrentThread();
+                return;
+            }
+            jmethodID& methodId = showToastMethodId;
+            if (!methodId) {
+                g_javaVM->DetachCurrentThread();
+                return;
+            }
+            jstring param = env->NewStringUTF(text.c_str());
+            env->CallStaticVoidMethod(kotlinClass, methodId, param);
+
+            g_javaVM->DetachCurrentThread();
+        }).detach();
+    }
+
+    void ShowToastFmt(const char* fmt, ...) {
+        GetParamStringResult(result);
+        ShowToast(result);
+    }
 }
diff --git a/app/src/main/cpp/GakumasLocalify/Log.h b/app/src/main/cpp/GakumasLocalify/Log.h
index 83f9f02..d411ebe 100644
--- a/app/src/main/cpp/GakumasLocalify/Log.h
+++ b/app/src/main/cpp/GakumasLocalify/Log.h
@@ -10,6 +10,9 @@ namespace GakumasLocal::Log {
     void ErrorFmt(const char* fmt, ...);
     void Debug(const char* msg);
     void DebugFmt(const char* fmt, ...);
+
+    void ShowToast(const char* text);
+    void ShowToastFmt(const char* fmt, ...);
 }
 
 #endif //GAKUMAS_LOCALIFY_LOG_H
diff --git a/app/src/main/cpp/GakumasLocalify/Misc.cpp b/app/src/main/cpp/GakumasLocalify/Misc.cpp
index 99909bf..1745880 100644
--- a/app/src/main/cpp/GakumasLocalify/Misc.cpp
+++ b/app/src/main/cpp/GakumasLocalify/Misc.cpp
@@ -2,6 +2,10 @@
 
 #include <codecvt>
 #include <locale>
+#include <jni.h>
+
+
+extern JavaVM* g_javaVM;
 
 
 namespace GakumasLocal::Misc {
@@ -14,4 +18,17 @@ namespace GakumasLocal::Misc {
         std::wstring_convert<std::codecvt_utf8_utf16<char16_t>, char16_t> utf16conv;
         return utf16conv.to_bytes(str.data(), str.data() + str.size());
     }
+
+    JNIEnv* GetJNIEnv() {
+        if (!g_javaVM) return nullptr;
+        JNIEnv* env = nullptr;
+        if (g_javaVM->GetEnv(reinterpret_cast<void**>(&env), JNI_VERSION_1_6) != JNI_OK) {
+            int status = g_javaVM->AttachCurrentThread(&env, nullptr);
+            if (status < 0) {
+                return nullptr;
+            }
+        }
+        return env;
+    }
+
 } // namespace UmaPyogin::Misc
diff --git a/app/src/main/cpp/GakumasLocalify/Misc.h b/app/src/main/cpp/GakumasLocalify/Misc.h
index 073062d..3932d3e 100644
--- a/app/src/main/cpp/GakumasLocalify/Misc.h
+++ b/app/src/main/cpp/GakumasLocalify/Misc.h
@@ -3,6 +3,7 @@
 
 #include <string>
 #include <string_view>
+#include <jni.h>
 
 namespace GakumasLocal {
     using OpaqueFunctionPointer = void (*)();
@@ -10,6 +11,7 @@ namespace GakumasLocal {
     namespace Misc {
         std::u16string ToUTF16(const std::string_view& str);
         std::string ToUTF8(const std::u16string_view& str);
+        JNIEnv* GetJNIEnv();
     }
 }
 
diff --git a/app/src/main/cpp/GakumasLocalify/Plugin.h b/app/src/main/cpp/GakumasLocalify/Plugin.h
index bba25f1..d4e986e 100644
--- a/app/src/main/cpp/GakumasLocalify/Plugin.h
+++ b/app/src/main/cpp/GakumasLocalify/Plugin.h
@@ -4,6 +4,7 @@
 #include "Misc.h"
 #include <string>
 #include <memory>
+#include <jni.h>
 
 namespace GakumasLocal {
     struct HookInstaller
diff --git a/app/src/main/cpp/GakumasLocalify/config/Config.cpp b/app/src/main/cpp/GakumasLocalify/config/Config.cpp
index 4915d36..b2f0c13 100644
--- a/app/src/main/cpp/GakumasLocalify/config/Config.cpp
+++ b/app/src/main/cpp/GakumasLocalify/config/Config.cpp
@@ -14,6 +14,14 @@ namespace GakumasLocal::Config {
     std::string liveCustomeHeadId = "";
     std::string liveCustomeCostumeId = "";
 
+    bool useCustomeGraphicSettings = false;
+    float renderScale = 0.77f;
+    int qualitySettingsLevel = 3;
+    int volumeIndex = 3;
+    int maxBufferPixel = 3384;
+    int reflectionQualityLevel = 4;
+    int lodQualityLevel = 4;
+
     void LoadConfig(const std::string& configStr) {
         try {
             const auto config = nlohmann::json::parse(configStr);
@@ -27,6 +35,13 @@ namespace GakumasLocal::Config {
             GetConfigItem(enableLiveCustomeDress);
             GetConfigItem(liveCustomeHeadId);
             GetConfigItem(liveCustomeCostumeId);
+            GetConfigItem(useCustomeGraphicSettings);
+            GetConfigItem(renderScale);
+            GetConfigItem(qualitySettingsLevel);
+            GetConfigItem(volumeIndex);
+            GetConfigItem(maxBufferPixel);
+            GetConfigItem(reflectionQualityLevel);
+            GetConfigItem(lodQualityLevel);
 
         }
         catch (std::exception& e) {
diff --git a/app/src/main/cpp/GakumasLocalify/config/Config.hpp b/app/src/main/cpp/GakumasLocalify/config/Config.hpp
index d6c1dea..0de274e 100644
--- a/app/src/main/cpp/GakumasLocalify/config/Config.hpp
+++ b/app/src/main/cpp/GakumasLocalify/config/Config.hpp
@@ -14,6 +14,15 @@ namespace GakumasLocal::Config {
     extern std::string liveCustomeHeadId;
     extern std::string liveCustomeCostumeId;
 
+    extern bool useCustomeGraphicSettings;
+    extern float renderScale;
+    extern int qualitySettingsLevel;
+    extern int volumeIndex;
+    extern int maxBufferPixel;
+
+    extern int reflectionQualityLevel;
+    extern int lodQualityLevel;
+
     void LoadConfig(const std::string& configStr);
 }
 
diff --git a/app/src/main/cpp/libMarryKotone.cpp b/app/src/main/cpp/libMarryKotone.cpp
index ea13a2b..112fbef 100644
--- a/app/src/main/cpp/libMarryKotone.cpp
+++ b/app/src/main/cpp/libMarryKotone.cpp
@@ -9,6 +9,10 @@
 #include "GakumasLocalify/camera/camera.hpp"
 #include "GakumasLocalify/config/Config.hpp"
 
+JavaVM* g_javaVM = nullptr;
+jclass g_gakumasHookMainClass = nullptr;
+jmethodID showToastMethodId = nullptr;
+
 namespace
 {
     class AndroidHookInstaller : public GakumasLocal::HookInstaller
@@ -40,11 +44,20 @@ namespace
     };
 }
 
+extern "C"
+JNIEXPORT jint JNICALL
+JNI_OnLoad(JavaVM* vm, void* reserved) {
+    g_javaVM = vm;
+    return JNI_VERSION_1_6;
+}
 
 extern "C"
 JNIEXPORT void JNICALL
 Java_io_github_chinosk_gakumas_localify_GakumasHookMain_initHook(JNIEnv *env, jclass clazz, jstring targetLibraryPath,
                                                                  jstring localizationFilesDir) {
+    g_gakumasHookMainClass = clazz;
+    showToastMethodId = env->GetStaticMethodID(clazz, "showToast", "(Ljava/lang/String;)V");
+
     const auto targetLibraryPathChars = env->GetStringUTFChars(targetLibraryPath, nullptr);
     const std::string targetLibraryPathStr = targetLibraryPathChars;
 
diff --git a/app/src/main/java/io/github/chinosk/gakumas/localify/GakumasHookMain.kt b/app/src/main/java/io/github/chinosk/gakumas/localify/GakumasHookMain.kt
index 60cc485..fd6b711 100644
--- a/app/src/main/java/io/github/chinosk/gakumas/localify/GakumasHookMain.kt
+++ b/app/src/main/java/io/github/chinosk/gakumas/localify/GakumasHookMain.kt
@@ -22,12 +22,12 @@ import android.widget.Toast
 import de.robv.android.xposed.XposedBridge
 import java.io.File
 
+val TAG = "GakumasLocalify"
 
 class GakumasHookMain : IXposedHookLoadPackage, IXposedHookZygoteInit {
     private lateinit var modulePath: String
     private var nativeLibLoadSuccess: Boolean
     private var alreadyInitialized = false
-    private val TAG = "GakumasLocalify"
     private val targetPackageName = "com.bandainamcoent.idolmaster_gakuen"
     private val nativeLibName = "MarryKotone"
 
@@ -115,20 +115,6 @@ class GakumasHookMain : IXposedHookLoadPackage, IXposedHookZygoteInit {
             })
     }
 
-    private fun showToast(message: String) {
-        val app = AndroidAppHelper.currentApplication()
-        val context = app?.applicationContext
-        if (context != null) {
-            val handler = Handler(Looper.getMainLooper())
-            handler.post {
-                Toast.makeText(context, message, Toast.LENGTH_SHORT).show()
-            }
-        }
-        else {
-            Log.e(TAG, "showToast: $message failed: applicationContext is null")
-        }
-    }
-
     fun initGkmsConfig(activity: Activity) {
         val intent = activity.intent
         val gkmsData = intent.getStringExtra("gkmsData")
@@ -160,8 +146,22 @@ class GakumasHookMain : IXposedHookLoadPackage, IXposedHookZygoteInit {
         external fun keyboardEvent(keyCode: Int, action: Int)
         @JvmStatic
         external fun loadConfig(configJsonStr: String)
-    }
 
+        @JvmStatic
+        fun showToast(message: String) {
+            val app = AndroidAppHelper.currentApplication()
+            val context = app?.applicationContext
+            if (context != null) {
+                val handler = Handler(Looper.getMainLooper())
+                handler.post {
+                    Toast.makeText(context, message, Toast.LENGTH_SHORT).show()
+                }
+            }
+            else {
+                Log.e(TAG, "showToast: $message failed: applicationContext is null")
+            }
+        }
+    }
 
     init {
         ShadowHook.init(
diff --git a/app/src/main/java/io/github/chinosk/gakumas/localify/MainActivity.kt b/app/src/main/java/io/github/chinosk/gakumas/localify/MainActivity.kt
index acd1f7d..323dd79 100644
--- a/app/src/main/java/io/github/chinosk/gakumas/localify/MainActivity.kt
+++ b/app/src/main/java/io/github/chinosk/gakumas/localify/MainActivity.kt
@@ -7,6 +7,9 @@ import android.os.Bundle
 import android.util.Log
 import android.widget.Toast
 import androidx.databinding.DataBindingUtil
+import androidx.databinding.ObservableField
+import com.google.android.material.textfield.TextInputEditText
+import com.google.android.material.textfield.TextInputLayout
 import com.google.gson.Gson
 import com.google.gson.JsonSyntaxException
 import io.github.chinosk.gakumas.localify.databinding.ActivityMainBinding
@@ -23,27 +26,33 @@ interface ConfigListener {
     fun onLiveCustomeDressChanged(value: Boolean)
     fun onLiveCustomeHeadIdChanged(s: CharSequence, start: Int, before: Int, count: Int)
     fun onLiveCustomeCostumeIdChanged(s: CharSequence, start: Int, before: Int, count: Int)
+    fun onUseCustomeGraphicSettingsChanged(value: Boolean)
+    fun onRenderScaleChanged(s: CharSequence, start: Int, before: Int, count: Int)
+    fun onQualitySettingsLevelChanged(s: CharSequence, start: Int, before: Int, count: Int)
+    fun onVolumeIndexChanged(s: CharSequence, start: Int, before: Int, count: Int)
+    fun onMaxBufferPixelChanged(s: CharSequence, start: Int, before: Int, count: Int)
+    fun onChangePresetQuality(level: Int)
+    fun onReflectionQualityLevelChanged(s: CharSequence, start: Int, before: Int, count: Int)
+    fun onLodQualityLevelChanged(s: CharSequence, start: Int, before: Int, count: Int)
 }
 
 class MainActivity : AppCompatActivity(), ConfigListener {
-    private lateinit var config: GakumasConfig
+    private lateinit var binding: ActivityMainBinding
     private val TAG = "GakumasLocalify"
 
     override fun onCreate(savedInstanceState: Bundle?) {
         super.onCreate(savedInstanceState)
         setContentView(R.layout.activity_main)
 
+        binding = DataBindingUtil.setContentView<ActivityMainBinding>(this, R.layout.activity_main)
         loadConfig()
+        binding.listener = this
 
         val requestData = intent.getStringExtra("gkmsData")
         if (requestData != null) {
             onClickStartGame()
             finish()
         }
-
-        val binding = DataBindingUtil.setContentView<ActivityMainBinding>(this, R.layout.activity_main)
-        binding.config = config
-        binding.listener = this
     }
 
     private fun showToast(message: String) {
@@ -63,34 +72,33 @@ class MainActivity : AppCompatActivity(), ConfigListener {
 
     private fun loadConfig() {
         val configStr = getConfigContent()
-        val config = try {
+        binding.config = try {
             Gson().fromJson(configStr, GakumasConfig::class.java)
         }
         catch (e: JsonSyntaxException) {
             showToast("配置文件异常,已重置: $e")
             Gson().fromJson("{}", GakumasConfig::class.java)
         }
-        this.config = config
         saveConfig()
     }
 
     private fun saveConfig() {
         val configFile = File(filesDir, "gkms-config.json")
-        configFile.writeText(Gson().toJson(config))
+        configFile.writeText(Gson().toJson(binding.config!!))
     }
 
     override fun onEnabledChanged(value: Boolean) {
-        config.enabled = value
+        binding.config!!.enabled = value
         saveConfig()
     }
 
     override fun onEnableFreeCameraChanged(value: Boolean) {
-        config.enableFreeCamera = value
+        binding.config!!.enableFreeCamera = value
         saveConfig()
     }
 
     override fun onUnlockAllLiveChanged(value: Boolean) {
-        config.unlockAllLive = value
+        binding.config!!.unlockAllLive = value
         saveConfig()
     }
 
@@ -103,7 +111,7 @@ class MainActivity : AppCompatActivity(), ConfigListener {
             } else {
                 valueStr.toInt()
             }
-            config.targetFrameRate = value
+            binding.config!!.targetFrameRate = value
             saveConfig()
         }
         catch (e: Exception) {
@@ -112,17 +120,62 @@ class MainActivity : AppCompatActivity(), ConfigListener {
     }
 
     override fun onLiveCustomeDressChanged(value: Boolean) {
-        config.enableLiveCustomeDress = value
+        binding.config!!.enableLiveCustomeDress = value
         saveConfig()
     }
 
     override fun onLiveCustomeCostumeIdChanged(s: CharSequence, start: Int, before: Int, count: Int) {
-        config.liveCustomeCostumeId = s.toString()
+        binding.config!!.liveCustomeCostumeId = s.toString()
+        saveConfig()
+    }
+
+    override fun onUseCustomeGraphicSettingsChanged(value: Boolean) {
+        binding.config!!.useCustomeGraphicSettings = value
+        saveConfig()
+    }
+
+    override fun onRenderScaleChanged(s: CharSequence, start: Int, before: Int, count: Int) {
+        binding.config!!.renderScale = try {
+            s.toString().toFloat()
+        }
+        catch (e: Exception) {
+            0.0f
+        }
+        saveConfig()
+    }
+
+    override fun onQualitySettingsLevelChanged(s: CharSequence, start: Int, before: Int, count: Int) {
+        binding.config!!.qualitySettingsLevel = try {
+            s.toString().toInt()
+        }
+        catch (e: Exception) {
+            0
+        }
+        saveConfig()
+    }
+
+    override fun onVolumeIndexChanged(s: CharSequence, start: Int, before: Int, count: Int) {
+        binding.config!!.volumeIndex = try {
+            s.toString().toInt()
+        }
+        catch (e: Exception) {
+            0
+        }
+        saveConfig()
+    }
+
+    override fun onMaxBufferPixelChanged(s: CharSequence, start: Int, before: Int, count: Int) {
+        binding.config!!.maxBufferPixel = try {
+            s.toString().toInt()
+        }
+        catch (e: Exception) {
+            0
+        }
         saveConfig()
     }
 
     override fun onLiveCustomeHeadIdChanged(s: CharSequence, start: Int, before: Int, count: Int) {
-        config.liveCustomeHeadId = s.toString()
+        binding.config!!.liveCustomeHeadId = s.toString()
         saveConfig()
     }
 
@@ -134,4 +187,78 @@ class MainActivity : AppCompatActivity(), ConfigListener {
         }
         startActivity(intent)
     }
+
+    override fun onReflectionQualityLevelChanged(s: CharSequence, start: Int, before: Int, count: Int) {
+        binding.config!!.reflectionQualityLevel = try {
+            val value = s.toString().toInt()
+            if (value > 5) 5 else value
+        }
+        catch (e: Exception) {
+            0
+        }
+        saveConfig()
+    }
+
+    override fun onLodQualityLevelChanged(s: CharSequence, start: Int, before: Int, count: Int) {
+        binding.config!!.lodQualityLevel = try {
+            val value = s.toString().toInt()
+            if (value > 5) 5 else value
+        }
+        catch (e: Exception) {
+            0
+        }
+        saveConfig()
+    }
+
+    override fun onChangePresetQuality(level: Int) {
+        when (level) {
+            0 -> {
+                binding.config!!.renderScale = 0.5f
+                binding.config!!.qualitySettingsLevel = 1
+                binding.config!!.volumeIndex = 0
+                binding.config!!.maxBufferPixel = 1024
+                binding.config!!.lodQualityLevel = 1
+                binding.config!!.reflectionQualityLevel = 1
+            }
+            1 -> {
+                binding.config!!.renderScale = 0.59f
+                binding.config!!.qualitySettingsLevel = 1
+                binding.config!!.volumeIndex = 1
+                binding.config!!.maxBufferPixel = 1440
+                binding.config!!.lodQualityLevel = 2
+                binding.config!!.reflectionQualityLevel = 2
+            }
+            2 -> {
+                binding.config!!.renderScale = 0.67f
+                binding.config!!.qualitySettingsLevel = 2
+                binding.config!!.volumeIndex = 2
+                binding.config!!.maxBufferPixel = 2538
+                binding.config!!.lodQualityLevel = 3
+                binding.config!!.reflectionQualityLevel = 3
+            }
+            3 -> {
+                binding.config!!.renderScale = 0.77f
+                binding.config!!.qualitySettingsLevel = 3
+                binding.config!!.volumeIndex = 3
+                binding.config!!.maxBufferPixel = 3384
+                binding.config!!.lodQualityLevel = 4
+                binding.config!!.reflectionQualityLevel = 4
+            }
+            4 -> {
+                binding.config!!.renderScale = 1.0f
+                binding.config!!.qualitySettingsLevel = 5
+                binding.config!!.volumeIndex = 4
+                binding.config!!.maxBufferPixel = 8190
+                binding.config!!.lodQualityLevel = 5
+                binding.config!!.reflectionQualityLevel = 5
+            }
+        }
+        binding.config = binding.config
+        binding.notifyChange()
+        saveConfig()
+    }
+
+    private fun showTextInputLayoutHint(view: TextInputLayout) {
+        showToast(view.hint.toString())
+    }
 }
\ No newline at end of file
diff --git a/app/src/main/java/io/github/chinosk/gakumas/localify/models/GakumasConfig.kt b/app/src/main/java/io/github/chinosk/gakumas/localify/models/GakumasConfig.kt
index 55b7ca6..9f2ab3f 100644
--- a/app/src/main/java/io/github/chinosk/gakumas/localify/models/GakumasConfig.kt
+++ b/app/src/main/java/io/github/chinosk/gakumas/localify/models/GakumasConfig.kt
@@ -1,12 +1,21 @@
 package io.github.chinosk.gakumas.localify.models
 
-data class GakumasConfig(
+import androidx.databinding.BaseObservable
+
+data class GakumasConfig (
     var enabled: Boolean = true,
     var enableFreeCamera: Boolean = false,
     var targetFrameRate: Int = 0,
     var unlockAllLive: Boolean = false,
     var enableLiveCustomeDress: Boolean = false,
     var liveCustomeHeadId: String = "",
-    var liveCustomeCostumeId: String = ""
-)
+    var liveCustomeCostumeId: String = "",
 
+    var useCustomeGraphicSettings: Boolean = false,
+    var renderScale: Float = 0.77f,
+    var qualitySettingsLevel: Int = 3,
+    var volumeIndex: Int = 3,
+    var maxBufferPixel: Int = 3384,
+    var reflectionQualityLevel: Int = 4,  // 0~5
+    var lodQualityLevel: Int = 4,  // 0~5
+)
diff --git a/app/src/main/res/drawable/table_row_border.xml b/app/src/main/res/drawable/table_row_border.xml
new file mode 100644
index 0000000..4d89eaa
--- /dev/null
+++ b/app/src/main/res/drawable/table_row_border.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<shape xmlns:android="http://schemas.android.com/apk/res/android"
+    android:shape="rectangle">
+    <stroke
+        android:width="1dp"
+        android:color="#ACACAC"/> <!-- 设置边框宽度和颜色 -->
+</shape>
diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml
index 63e08da..2069330 100644
--- a/app/src/main/res/layout/activity_main.xml
+++ b/app/src/main/res/layout/activity_main.xml
@@ -16,174 +16,477 @@
         android:padding="6sp"
         tools:context=".MainActivity">
 
-        <LinearLayout
+        <ScrollView
             android:layout_width="match_parent"
             android:layout_height="match_parent"
-            android:orientation="vertical"
             app:layout_constraintBottom_toBottomOf="parent"
             app:layout_constraintEnd_toEndOf="parent"
             app:layout_constraintStart_toStartOf="parent"
             app:layout_constraintTop_toTopOf="parent">
 
-            <TextView
-                android:id="@+id/textViewTitle"
+            <LinearLayout
                 android:layout_width="match_parent"
                 android:layout_height="wrap_content"
-                android:textColor="@color/black"
-                android:textSize="20sp"
-                android:text="@string/gakumas_localify" />
-
-            <Space
-                android:layout_width="match_parent"
-                android:layout_height="25sp" />
-
-            <TableLayout
-                android:layout_width="match_parent"
-                android:layout_height="match_parent"
                 android:orientation="vertical"
-                android:stretchColumns="0">
+                app:layout_constraintBottom_toBottomOf="parent"
+                app:layout_constraintEnd_toEndOf="parent"
+                app:layout_constraintStart_toStartOf="parent"
+                app:layout_constraintTop_toTopOf="parent">
 
-                <TableRow
+                <TextView
+                    android:id="@+id/textViewTitle"
                     android:layout_width="match_parent"
-                    android:layout_height="match_parent">
+                    android:layout_height="wrap_content"
+                    android:text="@string/gakumas_localify"
+                    android:textColor="@color/black"
+                    android:textSize="20sp" />
 
-                    <com.google.android.material.switchmaterial.SwitchMaterial
-                        android:id="@+id/SwitchEnablePlugin"
-                        android:layout_width="match_parent"
-                        android:layout_height="48dp"
-                        android:checked="@={config.enabled}"
-                        android:onCheckedChanged="@{(view, value) -> listener.onEnabledChanged(value)}"
-                        android:text="@string/enable_plugin" />
-                </TableRow>
-
-                <TableRow
+                <Space
                     android:layout_width="match_parent"
-                    android:layout_height="match_parent">
+                    android:layout_height="25sp" />
 
-                    <com.google.android.material.textfield.TextInputLayout
+                <TableLayout
+                    android:layout_width="match_parent"
+                    android:layout_height="match_parent"
+                    android:orientation="vertical"
+                    android:stretchColumns="0">
+
+                    <TableRow
                         android:layout_width="match_parent"
-                        android:layout_height="48dp"
-                        app:boxBackgroundColor="@android:color/transparent"
-                        android:background="@android:color/transparent"
-                        android:hint="@string/setFpsTitle" >
+                        android:layout_height="match_parent">
 
-                        <com.google.android.material.textfield.TextInputEditText
-                            android:id="@+id/editTextTargetFps"
+                        <com.google.android.material.switchmaterial.SwitchMaterial
+                            android:id="@+id/SwitchEnablePlugin"
                             android:layout_width="match_parent"
                             android:layout_height="48dp"
-                            android:ems="10"
-                            android:inputType="numberSigned"
-                            android:paddingStart="0dp"
-                            android:paddingEnd="0dp"
-                            android:paddingBottom="0dp"
-                            android:text="@={`` + config.targetFrameRate}"
-                            android:onTextChanged="@{(s, st, b, a) -> listener.onTargetFpsChanged(s, st, b, a)}"/>
+                            android:checked="@={config.enabled}"
+                            android:onCheckedChanged="@{(view, value) -> listener.onEnabledChanged(value)}"
+                            android:text="@string/enable_plugin" />
+                    </TableRow>
 
-                    </com.google.android.material.textfield.TextInputLayout>
-
-                </TableRow>
-
-                <TableRow
-                    android:layout_width="match_parent"
-                    android:layout_height="match_parent">
-
-                    <com.google.android.material.switchmaterial.SwitchMaterial
-                        android:id="@+id/SwitchEnableFreeCameraPlugin"
+                    <TableRow
                         android:layout_width="match_parent"
-                        android:layout_height="48dp"
-                        android:checked="@={config.enableFreeCamera}"
-                        android:onCheckedChanged="@{(view, value) -> listener.onEnableFreeCameraChanged(value)}"
-                        android:text="@string/enable_free_camera" />
-                </TableRow>
+                        android:layout_height="match_parent">
 
-                <TableRow
-                    android:layout_width="match_parent"
-                    android:layout_height="match_parent">
-
-                    <com.google.android.material.switchmaterial.SwitchMaterial
-                        android:id="@+id/SwitchUnlockAllLive"
-                        android:layout_width="match_parent"
-                        android:layout_height="48dp"
-                        android:checked="@={config.unlockAllLive}"
-                        android:onCheckedChanged="@{(view, value) -> listener.onUnlockAllLiveChanged(value)}"
-                        android:text="@string/unlockAllLive" />
-                </TableRow>
-
-                <TableRow
-                    android:layout_width="match_parent"
-                    android:layout_height="match_parent">
-
-                    <com.google.android.material.switchmaterial.SwitchMaterial
-                        android:id="@+id/SwitchLiveUseCustomeDress"
-                        android:layout_width="match_parent"
-                        android:layout_height="48dp"
-                        android:checked="@={config.enableLiveCustomeDress}"
-                        android:onCheckedChanged="@{(view, value) -> listener.onLiveCustomeDressChanged(value)}"
-                        android:text="@string/liveUseCustomeDress" />
-                </TableRow>
-
-                <TableRow
-                    android:layout_width="match_parent"
-                    android:layout_height="match_parent">
-
-                    <com.google.android.material.textfield.TextInputLayout
-                        android:layout_width="match_parent"
-                        android:layout_height="48dp"
-                        app:boxBackgroundColor="@android:color/transparent"
-                        android:background="@android:color/transparent"
-                        android:hint="@string/live_costume_head_id" >
-
-                        <com.google.android.material.textfield.TextInputEditText
-                            android:id="@+id/editTextLiveCustomeCharaId"
+                        <com.google.android.material.textfield.TextInputLayout
                             android:layout_width="match_parent"
-                            android:layout_height="match_parent"
-                            android:ems="10"
-                            android:paddingStart="0dp"
-                            android:paddingEnd="0dp"
-                            android:paddingBottom="0dp"
-                            android:text="@={config.liveCustomeHeadId}"
-                            android:onTextChanged="@{(s, st, b, a) -> listener.onLiveCustomeHeadIdChanged(s, st, b, a)}"/>
+                            android:layout_height="48dp"
+                            android:background="@android:color/transparent"
+                            android:hint="@string/setFpsTitle"
+                            app:boxBackgroundColor="@android:color/transparent">
 
-                    </com.google.android.material.textfield.TextInputLayout>
-                </TableRow>
+                            <com.google.android.material.textfield.TextInputEditText
+                                android:id="@+id/editTextTargetFps"
+                                android:layout_width="match_parent"
+                                android:layout_height="48dp"
+                                android:ems="10"
+                                android:inputType="numberSigned"
+                                android:onTextChanged="@{(s, st, b, a) -> listener.onTargetFpsChanged(s, st, b, a)}"
+                                android:paddingStart="0dp"
+                                android:paddingEnd="0dp"
+                                android:paddingBottom="0dp"
+                                android:text="@={`` + config.targetFrameRate}" />
 
-                <TableRow
-                    android:layout_width="match_parent"
-                    android:layout_height="match_parent">
-                    <com.google.android.material.textfield.TextInputLayout
+                        </com.google.android.material.textfield.TextInputLayout>
+
+                    </TableRow>
+
+                    <TableRow
                         android:layout_width="match_parent"
-                        android:layout_height="48dp"
-                        app:boxBackgroundColor="@android:color/transparent"
-                        android:background="@android:color/transparent"
-                        android:hint="@string/live_custome_dress_id" >
+                        android:layout_height="match_parent">
 
-                        <com.google.android.material.textfield.TextInputEditText
-                            android:id="@+id/editTextLiveCustomeCostumeId"
+                        <com.google.android.material.switchmaterial.SwitchMaterial
+                            android:id="@+id/SwitchEnableFreeCameraPlugin"
                             android:layout_width="match_parent"
-                            android:layout_height="match_parent"
-                            android:ems="10"
-                            android:paddingStart="0dp"
-                            android:paddingEnd="0dp"
-                            android:paddingBottom="0dp"
-                            android:text="@={config.liveCustomeCostumeId}"
-                            android:onTextChanged="@{(s, st, b, a) -> listener.onLiveCustomeCostumeIdChanged(s, st, b, a)}"/>
-                    </com.google.android.material.textfield.TextInputLayout>
-                </TableRow>
+                            android:layout_height="48dp"
+                            android:checked="@={config.enableFreeCamera}"
+                            android:onCheckedChanged="@{(view, value) -> listener.onEnableFreeCameraChanged(value)}"
+                            android:text="@string/enable_free_camera" />
+                    </TableRow>
 
-
-                <TableRow
-                    android:layout_width="match_parent"
-                    android:layout_height="match_parent">
-
-                    <com.google.android.material.button.MaterialButton
-                        android:id="@+id/StartGameButton"
+                    <TableRow
                         android:layout_width="match_parent"
-                        android:layout_height="48dp"
-                        android:onClick="@{() -> listener.onClickStartGame()}"
-                        android:text="@string/start_game" />
-                </TableRow>
+                        android:layout_height="match_parent">
 
-            </TableLayout>
-        </LinearLayout>
+                        <com.google.android.material.switchmaterial.SwitchMaterial
+                            android:id="@+id/SwitchUnlockAllLive"
+                            android:layout_width="match_parent"
+                            android:layout_height="48dp"
+                            android:checked="@={config.unlockAllLive}"
+                            android:onCheckedChanged="@{(view, value) -> listener.onUnlockAllLiveChanged(value)}"
+                            android:text="@string/unlockAllLive" />
+                    </TableRow>
+
+                    <TableRow
+                        android:layout_width="match_parent"
+                        android:layout_height="match_parent"
+                        android:background="@drawable/table_row_border">
+
+                        <TableLayout
+                            android:layout_width="wrap_content"
+                            android:layout_height="match_parent"
+                            android:orientation="vertical"
+                            android:paddingLeft="10sp"
+                            android:paddingRight="10sp"
+                            android:paddingBottom="10sp"
+                            android:stretchColumns="0">
+
+                            <TableRow
+                                android:layout_width="match_parent"
+                                android:layout_height="match_parent">
+
+                                <com.google.android.material.switchmaterial.SwitchMaterial
+                                    android:id="@+id/SwitchLiveUseCustomeDress"
+                                    android:layout_width="match_parent"
+                                    android:layout_height="48dp"
+                                    android:checked="@={config.enableLiveCustomeDress}"
+                                    android:onCheckedChanged="@{(view, value) -> listener.onLiveCustomeDressChanged(value)}"
+                                    android:text="@string/liveUseCustomeDress" />
+                            </TableRow>
+
+                            <TableRow
+                                android:layout_width="match_parent"
+                                android:layout_height="match_parent">
+
+                                <com.google.android.material.textfield.TextInputLayout
+                                    android:layout_width="match_parent"
+                                    android:layout_height="48dp"
+                                    android:background="@android:color/transparent"
+                                    android:hint="@string/live_costume_head_id"
+                                    app:boxBackgroundColor="@android:color/transparent">
+
+                                    <com.google.android.material.textfield.TextInputEditText
+                                        android:id="@+id/editTextLiveCustomeCharaId"
+                                        android:layout_width="match_parent"
+                                        android:layout_height="match_parent"
+                                        android:ems="10"
+                                        android:onTextChanged="@{(s, st, b, a) -> listener.onLiveCustomeHeadIdChanged(s, st, b, a)}"
+                                        android:paddingStart="0dp"
+                                        android:paddingEnd="0dp"
+                                        android:paddingBottom="0dp"
+                                        android:text="@={config.liveCustomeHeadId}" />
+
+                                </com.google.android.material.textfield.TextInputLayout>
+                            </TableRow>
+
+                            <TableRow
+                                android:layout_width="match_parent"
+                                android:layout_height="match_parent">
+
+                                <com.google.android.material.textfield.TextInputLayout
+                                    android:layout_width="match_parent"
+                                    android:layout_height="48dp"
+                                    android:background="@android:color/transparent"
+                                    android:hint="@string/live_custome_dress_id"
+                                    app:boxBackgroundColor="@android:color/transparent">
+
+                                    <com.google.android.material.textfield.TextInputEditText
+                                        android:id="@+id/editTextLiveCustomeCostumeId"
+                                        android:layout_width="match_parent"
+                                        android:layout_height="match_parent"
+                                        android:ems="10"
+                                        android:onTextChanged="@{(s, st, b, a) -> listener.onLiveCustomeCostumeIdChanged(s, st, b, a)}"
+                                        android:paddingStart="0dp"
+                                        android:paddingEnd="0dp"
+                                        android:paddingBottom="0dp"
+                                        android:text="@={config.liveCustomeCostumeId}" />
+                                </com.google.android.material.textfield.TextInputLayout>
+                            </TableRow>
+                        </TableLayout>
+
+                    </TableRow>
+
+                    <TableRow
+                        android:layout_width="match_parent"
+                        android:layout_height="match_parent"
+                        android:layout_marginTop="4sp"
+                        android:background="@drawable/table_row_border">
+
+                        <TableLayout
+                            android:layout_width="wrap_content"
+                            android:layout_height="match_parent"
+                            android:orientation="vertical"
+                            android:paddingLeft="10sp"
+                            android:paddingRight="10sp"
+                            android:paddingBottom="10sp"
+                            android:stretchColumns="0">
+
+                            <TableRow
+                                android:layout_width="match_parent"
+                                android:layout_height="match_parent">
+
+                                <com.google.android.material.switchmaterial.SwitchMaterial
+                                    android:id="@+id/SwitchUseCustomeGraphicSettings"
+                                    android:layout_width="match_parent"
+                                    android:layout_height="48dp"
+                                    android:checked="@={config.useCustomeGraphicSettings}"
+                                    android:onCheckedChanged="@{(view, value) -> listener.onUseCustomeGraphicSettingsChanged(value)}"
+                                    android:text="@string/useCustomeGraphicSettings" />
+                            </TableRow>
+
+
+                            <TableRow
+                                android:layout_width="match_parent"
+                                android:layout_height="match_parent">
+
+                                <LinearLayout
+                                    android:layout_width="match_parent"
+                                    android:layout_height="match_parent"
+                                    android:orientation="horizontal"
+                                    app:layout_constraintBottom_toBottomOf="parent"
+                                    app:layout_constraintEnd_toEndOf="parent"
+                                    app:layout_constraintStart_toStartOf="parent"
+                                    app:layout_constraintTop_toTopOf="parent">
+
+                                    <com.google.android.material.button.MaterialButton
+                                        android:id="@+id/qualityRecordButton"
+                                        android:layout_width="wrap_content"
+                                        android:layout_height="48dp"
+                                        android:layout_margin="1sp"
+                                        android:layout_weight="1"
+                                        android:minWidth="1sp"
+                                        android:onClick="@{() -> listener.onChangePresetQuality(4)}"
+                                        android:text="极高" />
+
+                                    <com.google.android.material.button.MaterialButton
+                                        android:id="@+id/qualityVeryHighButton"
+                                        android:layout_width="wrap_content"
+                                        android:layout_height="48dp"
+                                        android:layout_margin="1sp"
+                                        android:layout_weight="1"
+                                        android:minWidth="1sp"
+                                        android:onClick="@{() -> listener.onChangePresetQuality(3)}"
+                                        android:text="超高" />
+
+                                    <com.google.android.material.button.MaterialButton
+                                        android:id="@+id/qualityHighButton"
+                                        android:layout_width="wrap_content"
+                                        android:layout_height="48dp"
+                                        android:layout_margin="1sp"
+                                        android:layout_weight="1"
+                                        android:minWidth="1sp"
+                                        android:onClick="@{() -> listener.onChangePresetQuality(2)}"
+                                        android:text="高" />
+
+                                    <com.google.android.material.button.MaterialButton
+                                        android:id="@+id/qualityMidButton"
+                                        android:layout_width="wrap_content"
+                                        android:layout_height="48dp"
+                                        android:layout_margin="1sp"
+                                        android:layout_weight="1"
+                                        android:minWidth="1sp"
+                                        android:onClick="@{() -> listener.onChangePresetQuality(1)}"
+                                        android:text="中" />
+
+                                    <com.google.android.material.button.MaterialButton
+                                        android:id="@+id/qualityLowButton"
+                                        android:layout_width="wrap_content"
+                                        android:layout_height="48dp"
+                                        android:layout_weight="1"
+                                        android:minWidth="1sp"
+                                        android:onClick="@{() -> listener.onChangePresetQuality(0)}"
+                                        android:text="低" />
+
+                                </LinearLayout>
+
+                            </TableRow>
+
+                            <TableRow
+                                android:layout_width="match_parent"
+                                android:layout_height="match_parent">
+
+                                <TableLayout
+                                    android:layout_width="wrap_content"
+                                    android:layout_height="match_parent"
+                                    android:orientation="vertical">
+
+                                    <TableRow
+                                        android:layout_width="match_parent"
+                                        android:layout_height="match_parent"
+                                        android:weightSum="2">
+
+                                        <com.google.android.material.textfield.TextInputLayout
+                                            android:id="@+id/editTextRenderScaleLayout"
+                                            android:layout_width="match_parent"
+                                            android:layout_height="48dp"
+                                            android:layout_weight="1"
+                                            android:background="@android:color/transparent"
+                                            android:hint="@string/renderscale"
+                                            app:boxBackgroundColor="@android:color/transparent">
+
+                                            <com.google.android.material.textfield.TextInputEditText
+                                                android:id="@+id/editTextRenderScale"
+                                                android:layout_width="match_parent"
+                                                android:layout_height="match_parent"
+                                                android:ems="10"
+                                                android:hint="0.5/0.59/0.67/0.77/1.0"
+                                                android:inputType="numberDecimal"
+                                                android:onTextChanged="@{(s, st, b, a) -> listener.onRenderScaleChanged(s, st, b, a)}"
+                                                android:paddingStart="0dp"
+                                                android:paddingEnd="0dp"
+                                                android:paddingBottom="0dp"
+                                                android:text="@={`` + config.renderScale}" />
+
+                                        </com.google.android.material.textfield.TextInputLayout>
+
+                                        <com.google.android.material.textfield.TextInputLayout
+                                            android:id="@+id/editTextQualitySettingsLevelLayout"
+                                            android:layout_width="match_parent"
+                                            android:layout_height="48dp"
+                                            android:layout_weight="1"
+                                            android:background="@android:color/transparent"
+                                            android:hint="QualityLevel (1/1/2/3/5)"
+                                            app:boxBackgroundColor="@android:color/transparent">
+
+                                            <com.google.android.material.textfield.TextInputEditText
+                                                android:id="@+id/editTextQualitySettingsLevel"
+                                                android:layout_width="match_parent"
+                                                android:layout_height="match_parent"
+                                                android:ems="10"
+                                                android:hint="1/1/2/3/5"
+                                                android:inputType="number"
+                                                android:onTextChanged="@{(s, st, b, a) -> listener.onQualitySettingsLevelChanged(s, st, b, a)}"
+                                                android:paddingStart="0dp"
+                                                android:paddingEnd="0dp"
+                                                android:paddingBottom="0dp"
+                                                android:text="@={`` + config.qualitySettingsLevel}" />
+
+                                        </com.google.android.material.textfield.TextInputLayout>
+
+
+                                    </TableRow>
+
+                                    <TableRow
+                                        android:layout_width="match_parent"
+                                        android:layout_height="match_parent"
+                                        android:weightSum="2">
+
+                                        <com.google.android.material.textfield.TextInputLayout
+                                            android:id="@+id/editTextVolumeIndexLayout"
+                                            android:layout_width="match_parent"
+                                            android:layout_height="48dp"
+                                            android:layout_weight="1"
+                                            android:background="@android:color/transparent"
+                                            android:hint="VolumeIndex (0/1/2/3/4)"
+                                            app:boxBackgroundColor="@android:color/transparent">
+
+                                            <com.google.android.material.textfield.TextInputEditText
+                                                android:id="@+id/editTextVolumeIndex"
+                                                android:layout_width="match_parent"
+                                                android:layout_height="match_parent"
+                                                android:ems="10"
+                                                android:hint="0/1/2/3/4"
+                                                android:inputType="number"
+                                                android:onTextChanged="@{(s, st, b, a) -> listener.onVolumeIndexChanged(s, st, b, a)}"
+                                                android:paddingStart="0dp"
+                                                android:paddingEnd="0dp"
+                                                android:paddingBottom="0dp"
+                                                android:text="@={`` + config.volumeIndex}" />
+
+                                        </com.google.android.material.textfield.TextInputLayout>
+
+                                        <com.google.android.material.textfield.TextInputLayout
+                                            android:id="@+id/editTextMaxBufferPixelLayout"
+                                            android:layout_width="match_parent"
+                                            android:layout_height="48dp"
+                                            android:layout_weight="1"
+                                            android:background="@android:color/transparent"
+                                            android:hint="MaxBufferPixel (1024/1440/2538/3384/8190)"
+                                            app:boxBackgroundColor="@android:color/transparent">
+
+                                            <com.google.android.material.textfield.TextInputEditText
+                                                android:id="@+id/editTextMaxBufferPixel"
+                                                android:layout_width="match_parent"
+                                                android:layout_height="match_parent"
+                                                android:ems="10"
+                                                android:hint="1024/1440/2538/3384/8190"
+                                                android:inputType="number"
+                                                android:onTextChanged="@{(s, st, b, a) -> listener.onMaxBufferPixelChanged(s, st, b, a)}"
+                                                android:paddingStart="0dp"
+                                                android:paddingEnd="0dp"
+                                                android:paddingBottom="0dp"
+                                                android:text="@={`` + config.maxBufferPixel}" />
+
+                                        </com.google.android.material.textfield.TextInputLayout>
+
+
+                                    </TableRow>
+
+                                    <TableRow
+                                        android:layout_width="match_parent"
+                                        android:layout_height="match_parent"
+                                        android:weightSum="2">
+
+                                        <com.google.android.material.textfield.TextInputLayout
+                                            android:layout_width="match_parent"
+                                            android:layout_height="48dp"
+                                            android:layout_weight="1"
+                                            android:background="@android:color/transparent"
+                                            android:hint="ReflectionLevel (0~5)"
+                                            app:boxBackgroundColor="@android:color/transparent">
+
+                                            <com.google.android.material.textfield.TextInputEditText
+                                                android:id="@+id/editTextReflectionQualityLevel"
+                                                android:layout_width="match_parent"
+                                                android:layout_height="match_parent"
+                                                android:ems="10"
+                                                android:hint="0/1/2/3/4/5"
+                                                android:inputType="number"
+                                                android:onTextChanged="@{(s, st, b, a) -> listener.onReflectionQualityLevelChanged(s, st, b, a)}"
+                                                android:paddingStart="0dp"
+                                                android:paddingEnd="0dp"
+                                                android:paddingBottom="0dp"
+                                                android:text="@={`` + config.reflectionQualityLevel}" />
+
+                                        </com.google.android.material.textfield.TextInputLayout>
+
+                                        <com.google.android.material.textfield.TextInputLayout
+                                            android:layout_width="match_parent"
+                                            android:layout_height="48dp"
+                                            android:layout_weight="1"
+                                            android:background="@android:color/transparent"
+                                            android:hint="LOD Level (0~5)"
+                                            app:boxBackgroundColor="@android:color/transparent">
+
+                                            <com.google.android.material.textfield.TextInputEditText
+                                                android:id="@+id/editTextLodQualityLevel"
+                                                android:layout_width="match_parent"
+                                                android:layout_height="match_parent"
+                                                android:ems="10"
+                                                android:hint="0/1/2/3/4/5"
+                                                android:inputType="number"
+                                                android:onTextChanged="@{(s, st, b, a) -> listener.onLodQualityLevelChanged(s, st, b, a)}"
+                                                android:paddingStart="0dp"
+                                                android:paddingEnd="0dp"
+                                                android:paddingBottom="0dp"
+                                                android:text="@={`` + config.lodQualityLevel}" />
+
+                                        </com.google.android.material.textfield.TextInputLayout>
+
+
+                                    </TableRow>
+
+                                </TableLayout>
+                            </TableRow>
+                        </TableLayout>
+
+                    </TableRow>
+
+                    <TableRow
+                        android:layout_width="match_parent"
+                        android:layout_height="match_parent">
+
+                        <com.google.android.material.button.MaterialButton
+                            android:id="@+id/StartGameButton"
+                            android:layout_width="match_parent"
+                            android:layout_height="48dp"
+                            android:onClick="@{() -> listener.onClickStartGame()}"
+                            android:text="@string/start_game" />
+                    </TableRow>
+
+                </TableLayout>
+            </LinearLayout>
+
+        </ScrollView>
     </androidx.constraintlayout.widget.ConstraintLayout>
 </layout>
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index 12d3458..093b278 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -9,4 +9,6 @@
     <string name="liveUseCustomeDress">Live 使用自定义角色</string>
     <string name="live_costume_head_id">Live 自定义头部 ID (例: costume_head_hski-cstm-0002)</string>
     <string name="live_custome_dress_id">Live 自定义服装 ID (例: hski-cstm-0002)</string>
+    <string name="useCustomeGraphicSettings">使用自定义画质设置</string>
+    <string name="renderscale">RenderScale (0.5/0.59/0.67/0.77/1.0)</string>
 </resources>
\ No newline at end of file