rip out turtle specific options
Some checks failed
Build Go/Fyne App for macOS ARM64 / build (push) Has been cancelled

This commit is contained in:
2025-07-20 14:54:38 -07:00
parent 488d10cb8b
commit 9b04ad7fd0
18 changed files with 164 additions and 954 deletions

View File

@@ -5,6 +5,7 @@ import (
"errors"
"fmt"
"io"
"log"
"os"
"os/exec"
"path/filepath"
@@ -19,22 +20,22 @@ import (
"fyne.io/fyne/v2/dialog"
)
func PatchTurtleWoW(myWindow fyne.Window, updateAllStatuses func()) {
func PatchEpoch(myWindow fyne.Window, updateAllStatuses func()) {
// TODO: patch vanilla 3.3.5 to epoch
log.Fatal("FIXME")
debug.Println("Patch TurtleWoW clicked")
if paths.TurtlewowPath == "" {
if paths.EpochPath == "" {
dialog.ShowError(fmt.Errorf("TurtleWoW path not set. Please set it first."), myWindow)
return
}
targetWinerosettaDll := filepath.Join(paths.TurtlewowPath, "winerosetta.dll")
targetD3d9Dll := filepath.Join(paths.TurtlewowPath, "d3d9.dll")
targetLibSiliconPatchDll := filepath.Join(paths.TurtlewowPath, "libSiliconPatch.dll")
targetRosettaX87Dir := filepath.Join(paths.TurtlewowPath, "rosettax87")
dllsTextFile := filepath.Join(paths.TurtlewowPath, "dlls.txt")
targetWinerosettaDll := filepath.Join(paths.EpochPath, "winerosetta.dll")
targetD3d9Dll := filepath.Join(paths.EpochPath, "d3d9.dll")
targetRosettaX87Dir := filepath.Join(paths.EpochPath, "rosettax87")
dllsTextFile := filepath.Join(paths.EpochPath, "dlls.txt")
filesToCopy := map[string]string{
"winerosetta/winerosetta.dll": targetWinerosettaDll,
"winerosetta/d3d9.dll": targetD3d9Dll,
"winerosetta/libSiliconPatch.dll": targetLibSiliconPatchDll,
"winerosetta/winerosetta.dll": targetWinerosettaDll,
"winerosetta/d3d9.dll": targetD3d9Dll,
}
for resourceName, destPath := range filesToCopy {
@@ -57,7 +58,7 @@ func PatchTurtleWoW(myWindow fyne.Window, updateAllStatuses func()) {
errMsg := fmt.Sprintf("failed to open bundled resource %s: %v", resourceName, err)
dialog.ShowError(errors.New(errMsg), myWindow)
debug.Println(errMsg)
paths.PatchesAppliedTurtleWoW = false
paths.PatchesAppliedEpoch = false
updateAllStatuses()
return
}
@@ -67,7 +68,7 @@ func PatchTurtleWoW(myWindow fyne.Window, updateAllStatuses func()) {
errMsg := fmt.Sprintf("failed to create destination file %s: %v", destPath, err)
dialog.ShowError(errors.New(errMsg), myWindow)
debug.Println(errMsg)
paths.PatchesAppliedTurtleWoW = false
paths.PatchesAppliedEpoch = false
updateAllStatuses()
return
}
@@ -78,7 +79,7 @@ func PatchTurtleWoW(myWindow fyne.Window, updateAllStatuses func()) {
errMsg := fmt.Sprintf("failed to copy bundled resource %s to %s: %v", resourceName, destPath, err)
dialog.ShowError(errors.New(errMsg), myWindow)
debug.Println(errMsg)
paths.PatchesAppliedTurtleWoW = false
paths.PatchesAppliedEpoch = false
updateAllStatuses()
return
}
@@ -93,7 +94,7 @@ func PatchTurtleWoW(myWindow fyne.Window, updateAllStatuses func()) {
errMsg := fmt.Sprintf("failed to create directory %s: %v", targetRosettaX87Dir, err)
dialog.ShowError(errors.New(errMsg), myWindow)
debug.Println(errMsg)
paths.PatchesAppliedTurtleWoW = false
paths.PatchesAppliedEpoch = false
updateAllStatuses()
return
}
@@ -110,7 +111,7 @@ func PatchTurtleWoW(myWindow fyne.Window, updateAllStatuses func()) {
errMsg := fmt.Sprintf("failed to open bundled resource %s: %v", resourceName, err)
dialog.ShowError(errors.New(errMsg), myWindow)
debug.Println(errMsg)
paths.PatchesAppliedTurtleWoW = false
paths.PatchesAppliedEpoch = false
updateAllStatuses()
return
}
@@ -120,7 +121,7 @@ func PatchTurtleWoW(myWindow fyne.Window, updateAllStatuses func()) {
errMsg := fmt.Sprintf("failed to create destination file %s: %v", destPath, err)
dialog.ShowError(errors.New(errMsg), myWindow)
debug.Println(errMsg)
paths.PatchesAppliedTurtleWoW = false
paths.PatchesAppliedEpoch = false
updateAllStatuses()
return
}
@@ -131,7 +132,7 @@ func PatchTurtleWoW(myWindow fyne.Window, updateAllStatuses func()) {
errMsg := fmt.Sprintf("failed to copy bundled resource %s to %s: %v", resourceName, destPath, err)
dialog.ShowError(errors.New(errMsg), myWindow)
debug.Println(errMsg)
paths.PatchesAppliedTurtleWoW = false
paths.PatchesAppliedEpoch = false
updateAllStatuses()
return
}
@@ -143,7 +144,7 @@ func PatchTurtleWoW(myWindow fyne.Window, updateAllStatuses func()) {
errMsg := fmt.Sprintf("failed to set execute permission for %s: %v", destPath, err)
dialog.ShowError(errors.New(errMsg), myWindow)
debug.Println(errMsg)
paths.PatchesAppliedTurtleWoW = false
paths.PatchesAppliedEpoch = false
updateAllStatuses()
return
}
@@ -153,34 +154,11 @@ func PatchTurtleWoW(myWindow fyne.Window, updateAllStatuses func()) {
debug.Printf("Checking dlls.txt file at: %s", dllsTextFile)
winerosettaEntry := "winerosetta.dll"
libSiliconPatchEntry := "libSiliconPatch.dll"
needsWinerosettaUpdate := true
needsLibSiliconPatchUpdate := true
// Check user's preference for libSiliconPatch and shadowLOD
prefs, _ := utils.LoadPrefs()
// Enable by default unless user has explicitly disabled them
shouldEnableLibSiliconPatch := true
shouldEnableShadowLOD := true
// If user has manually disabled these settings, respect their choice
if prefs.UserDisabledLibSiliconPatch {
shouldEnableLibSiliconPatch = false
debug.Printf("libSiliconPatch disabled by user choice")
} else {
// Enable by default and update preferences
prefs.EnableLibSiliconPatch = true
}
if prefs.UserDisabledShadowLOD {
shouldEnableShadowLOD = false
debug.Printf("shadowLOD disabled by user choice")
} else {
// Enable by default and update preferences
prefs.SetShadowLOD0 = true
}
// Save updated preferences
utils.SavePrefs(prefs)
@@ -190,21 +168,11 @@ func PatchTurtleWoW(myWindow fyne.Window, updateAllStatuses func()) {
debug.Printf("dlls.txt already contains %s", winerosettaEntry)
needsWinerosettaUpdate = false
}
if strings.Contains(fileContent, libSiliconPatchEntry) {
debug.Printf("dlls.txt already contains %s", libSiliconPatchEntry)
needsLibSiliconPatchUpdate = false
}
} else {
debug.Printf("dlls.txt not found, will create a new one")
}
// Only add libSiliconPatch if user wants it enabled
if !shouldEnableLibSiliconPatch {
needsLibSiliconPatchUpdate = false
debug.Printf("libSiliconPatch disabled by user preference, will not add to dlls.txt")
}
if needsWinerosettaUpdate || needsLibSiliconPatchUpdate {
if needsWinerosettaUpdate {
var fileContentBytes []byte
var err error
if utils.PathExists(dllsTextFile) {
@@ -229,12 +197,6 @@ func PatchTurtleWoW(myWindow fyne.Window, updateAllStatuses func()) {
debug.Printf("Adding %s to dlls.txt", winerosettaEntry)
}
}
if needsLibSiliconPatchUpdate && shouldEnableLibSiliconPatch {
if !strings.Contains(updatedContent, libSiliconPatchEntry+"\n") {
updatedContent += libSiliconPatchEntry + "\n"
debug.Printf("Adding %s to dlls.txt", libSiliconPatchEntry)
}
}
if err := os.WriteFile(dllsTextFile, []byte(updatedContent), 0644); err != nil {
errMsg := fmt.Sprintf("failed to update dlls.txt: %v", err)
@@ -245,33 +207,6 @@ func PatchTurtleWoW(myWindow fyne.Window, updateAllStatuses func()) {
}
}
// If user has disabled libSiliconPatch, make sure it's removed from dlls.txt
if !shouldEnableLibSiliconPatch {
if err := disableLibSiliconPatchInDlls(); err != nil {
debug.Printf("Warning: failed to remove libSiliconPatch from dlls.txt: %v", err)
}
}
// Always apply vertex animation shaders setting to Config.wtf
if err := applyVertexAnimShadersSetting(); err != nil {
debug.Printf("Warning: failed to apply vertex animation shaders setting to Config.wtf: %v", err)
// Continue with patching even if Config.wtf update fails
}
// Apply shadowLOD setting to Config.wtf for FPS optimization
// Use shouldEnableShadowLOD which accounts for first-time patching
if shouldEnableShadowLOD {
if err := applyShadowLODSetting(); err != nil {
debug.Printf("Warning: failed to apply shadowLOD setting to Config.wtf: %v", err)
// Continue with patching even if Config.wtf update fails
}
} else {
// If user has disabled shadowLOD, make sure it's removed from Config.wtf
if err := removeShadowLODSetting(); err != nil {
debug.Printf("Warning: failed to remove shadowLOD setting from Config.wtf: %v", err)
}
}
debug.Println("TurtleWoW patching with bundled resources completed successfully.")
dialog.ShowInformation("Success", "TurtleWoW patching process completed using bundled resources.", myWindow)
updateAllStatuses()
@@ -339,19 +274,21 @@ func PatchCrossOver(myWindow fyne.Window, updateAllStatuses func()) {
updateAllStatuses()
}
func UnpatchTurtleWoW(myWindow fyne.Window, updateAllStatuses func()) {
func UnpatchEpoch(myWindow fyne.Window, updateAllStatuses func()) {
// TODO: unpatch epoch
log.Fatal("fixme")
debug.Println("Unpatch TurtleWoW clicked")
if paths.TurtlewowPath == "" {
if paths.EpochPath == "" {
dialog.ShowError(fmt.Errorf("TurtleWoW path not set. Please set it first."), myWindow)
return
}
// Files to remove
winerosettaDllPath := filepath.Join(paths.TurtlewowPath, "winerosetta.dll")
d3d9DllPath := filepath.Join(paths.TurtlewowPath, "d3d9.dll")
libSiliconPatchDllPath := filepath.Join(paths.TurtlewowPath, "libSiliconPatch.dll")
rosettaX87DirPath := filepath.Join(paths.TurtlewowPath, "rosettax87")
dllsTextFile := filepath.Join(paths.TurtlewowPath, "dlls.txt")
winerosettaDllPath := filepath.Join(paths.EpochPath, "winerosetta.dll")
d3d9DllPath := filepath.Join(paths.EpochPath, "d3d9.dll")
libSiliconPatchDllPath := filepath.Join(paths.EpochPath, "libSiliconPatch.dll")
rosettaX87DirPath := filepath.Join(paths.EpochPath, "rosettax87")
dllsTextFile := filepath.Join(paths.EpochPath, "dlls.txt")
// Remove the rosettaX87 directory
if utils.DirExists(rosettaX87DirPath) {
@@ -410,17 +347,8 @@ func UnpatchTurtleWoW(myWindow fyne.Window, updateAllStatuses func()) {
}
}
// Remove shadowLOD setting from Config.wtf - only if it was applied via graphics settings
prefs, _ := utils.LoadPrefs()
if prefs.SetShadowLOD0 {
if err := removeShadowLODSetting(); err != nil {
debug.Printf("Warning: failed to remove shadowLOD setting from Config.wtf: %v", err)
// Continue with unpatching even if Config.wtf update fails
}
}
debug.Println("TurtleWoW unpatching completed successfully.")
paths.PatchesAppliedTurtleWoW = false
paths.PatchesAppliedEpoch = false
dialog.ShowInformation("Success", "TurtleWoW unpatching process completed.", myWindow)
updateAllStatuses()
}
@@ -455,42 +383,6 @@ func UnpatchCrossOver(myWindow fyne.Window, updateAllStatuses func()) {
updateAllStatuses()
}
// applyShadowLODSetting applies the shadowLOD setting to Config.wtf for FPS optimization
func applyShadowLODSetting() error {
if paths.TurtlewowPath == "" {
return fmt.Errorf("TurtleWoW path not set")
}
configPath := filepath.Join(paths.TurtlewowPath, "WTF", "Config.wtf")
// Create WTF directory if it doesn't exist
wtfDir := filepath.Dir(configPath)
if err := os.MkdirAll(wtfDir, 0755); err != nil {
return fmt.Errorf("failed to create WTF directory: %v", err)
}
var configText string
// Read existing config if it exists
if content, err := os.ReadFile(configPath); err == nil {
configText = string(content)
} else {
debug.Printf("Config.wtf not found, creating new file")
configText = ""
}
// Apply shadowLOD setting
configText = updateOrAddConfigSetting(configText, "shadowLOD", "0")
// Write the updated config back to file
if err := os.WriteFile(configPath, []byte(configText), 0644); err != nil {
return fmt.Errorf("failed to write Config.wtf: %v", err)
}
debug.Printf("Successfully applied shadowLOD setting to Config.wtf")
return nil
}
// updateOrAddConfigSetting updates an existing setting or adds a new one if it doesn't exist
func updateOrAddConfigSetting(configText, setting, value string) string {
// Create regex pattern to match the setting
@@ -529,27 +421,6 @@ func removeConfigSetting(configText, setting string) string {
return configText
}
// CheckShadowLODSetting checks if the shadowLOD setting is correctly applied in Config.wtf
func CheckShadowLODSetting() bool {
if paths.TurtlewowPath == "" {
return false
}
configPath := filepath.Join(paths.TurtlewowPath, "WTF", "Config.wtf")
if _, err := os.Stat(configPath); os.IsNotExist(err) {
return false
}
content, err := os.ReadFile(configPath)
if err != nil {
return false
}
configText := string(content)
return isConfigSettingCorrect(configText, "shadowLOD", "0")
}
// isConfigSettingCorrect checks if a specific setting has the correct value in the config text
func isConfigSettingCorrect(configText, setting, expectedValue string) bool {
// Create regex pattern to match the setting
@@ -564,365 +435,3 @@ func isConfigSettingCorrect(configText, setting, expectedValue string) bool {
currentValue := matches[1]
return currentValue == expectedValue
}
// removeShadowLODSetting removes the shadowLOD setting from Config.wtf
func removeShadowLODSetting() error {
if paths.TurtlewowPath == "" {
return fmt.Errorf("TurtleWoW path not set")
}
configPath := filepath.Join(paths.TurtlewowPath, "WTF", "Config.wtf")
if _, err := os.Stat(configPath); os.IsNotExist(err) {
debug.Printf("Config.wtf not found, nothing to remove")
return nil
}
content, err := os.ReadFile(configPath)
if err != nil {
return fmt.Errorf("failed to read Config.wtf: %v", err)
}
configText := string(content)
// Remove shadowLOD setting if it exists
pattern := fmt.Sprintf(`SET\s+%s\s+"[^"]*"[\r\n]*`, regexp.QuoteMeta("shadowLOD"))
re := regexp.MustCompile(pattern)
if re.MatchString(configText) {
configText = re.ReplaceAllString(configText, "")
debug.Printf("Removed shadowLOD setting from Config.wtf")
// Write the updated config back to file
if err := os.WriteFile(configPath, []byte(configText), 0644); err != nil {
return fmt.Errorf("failed to write Config.wtf: %v", err)
}
debug.Printf("Successfully updated Config.wtf")
} else {
debug.Printf("shadowLOD setting not found in Config.wtf, nothing to remove")
}
return nil
}
// applyVertexAnimShadersSetting applies the vertex animation shaders setting to Config.wtf
func applyVertexAnimShadersSetting() error {
if paths.TurtlewowPath == "" {
return fmt.Errorf("TurtleWoW path not set")
}
configPath := filepath.Join(paths.TurtlewowPath, "WTF", "Config.wtf")
// Create WTF directory if it doesn't exist
wtfDir := filepath.Dir(configPath)
if err := os.MkdirAll(wtfDir, 0755); err != nil {
return fmt.Errorf("failed to create WTF directory: %v", err)
}
var configText string
// Read existing config if it exists
if content, err := os.ReadFile(configPath); err == nil {
configText = string(content)
} else {
debug.Printf("Config.wtf not found, creating new file")
configText = ""
}
// Apply vertex animation shaders setting
configText = updateOrAddConfigSetting(configText, "M2UseShaders", "1")
// Write the updated config back to file
if err := os.WriteFile(configPath, []byte(configText), 0644); err != nil {
return fmt.Errorf("failed to write Config.wtf: %v", err)
}
debug.Printf("Successfully applied vertex animation shaders setting to Config.wtf")
return nil
}
// ApplyGraphicsSettings applies the selected graphics settings to Config.wtf
func ApplyGraphicsSettings(myWindow fyne.Window) error {
prefs, err := utils.LoadPrefs()
if err != nil {
return fmt.Errorf("failed to load preferences: %v", err)
}
if paths.TurtlewowPath == "" {
return fmt.Errorf("TurtleWoW path not set")
}
configPath := filepath.Join(paths.TurtlewowPath, "WTF", "Config.wtf")
// Create WTF directory if it doesn't exist
wtfDir := filepath.Dir(configPath)
if err := os.MkdirAll(wtfDir, 0755); err != nil {
return fmt.Errorf("failed to create WTF directory: %v", err)
}
var configText string
// Read existing config if it exists
if content, err := os.ReadFile(configPath); err == nil {
configText = string(content)
} else {
debug.Printf("Config.wtf not found, creating new file")
configText = ""
}
// Apply or remove graphics settings based on user preferences
if prefs.ReduceTerrainDistance {
configText = updateOrAddConfigSetting(configText, "farclip", "177")
} else {
configText = removeConfigSetting(configText, "farclip")
}
if prefs.SetMultisampleTo2x {
configText = updateOrAddConfigSetting(configText, "gxMultisample", "2")
} else {
configText = removeConfigSetting(configText, "gxMultisample")
}
if prefs.SetShadowLOD0 {
configText = updateOrAddConfigSetting(configText, "shadowLOD", "0")
} else {
configText = removeConfigSetting(configText, "shadowLOD")
}
// Handle libSiliconPatch.dll in dlls.txt (only if DLL exists)
libSiliconPatchPath := filepath.Join(paths.TurtlewowPath, "libSiliconPatch.dll")
if utils.PathExists(libSiliconPatchPath) {
if prefs.EnableLibSiliconPatch {
if err := enableLibSiliconPatchInDlls(); err != nil {
debug.Printf("Warning: failed to enable libSiliconPatch in dlls.txt: %v", err)
}
} else {
if err := disableLibSiliconPatchInDlls(); err != nil {
debug.Printf("Warning: failed to disable libSiliconPatch in dlls.txt: %v", err)
}
}
}
// Write the updated config back to file
if err := os.WriteFile(configPath, []byte(configText), 0644); err != nil {
return fmt.Errorf("failed to write Config.wtf: %v", err)
}
debug.Printf("Successfully applied graphics settings to Config.wtf")
return nil
}
// CheckGraphicsSettings checks if the graphics settings are correctly applied in Config.wtf
func CheckGraphicsSettings() (bool, bool, bool) {
prefs, _ := utils.LoadPrefs()
if paths.TurtlewowPath == "" {
return false, false, false
}
configPath := filepath.Join(paths.TurtlewowPath, "WTF", "Config.wtf")
if _, err := os.Stat(configPath); os.IsNotExist(err) {
return false, false, false
}
content, err := os.ReadFile(configPath)
if err != nil {
return false, false, false
}
configText := string(content)
terrainCorrect := !prefs.ReduceTerrainDistance || isConfigSettingCorrect(configText, "farclip", "177")
multisampleCorrect := !prefs.SetMultisampleTo2x || isConfigSettingCorrect(configText, "gxMultisample", "2")
shadowCorrect := !prefs.SetShadowLOD0 || isConfigSettingCorrect(configText, "shadowLOD", "0")
return terrainCorrect, multisampleCorrect, shadowCorrect
}
// LoadGraphicsSettingsFromConfig reads Config.wtf and updates preferences with current settings
func LoadGraphicsSettingsFromConfig() error {
if paths.TurtlewowPath == "" {
return fmt.Errorf("TurtleWoW path not set")
}
configPath := filepath.Join(paths.TurtlewowPath, "WTF", "Config.wtf")
// If Config.wtf doesn't exist, nothing to load
if _, err := os.Stat(configPath); os.IsNotExist(err) {
debug.Printf("Config.wtf not found, using default graphics settings")
return nil
}
content, err := os.ReadFile(configPath)
if err != nil {
return fmt.Errorf("failed to read Config.wtf: %v", err)
}
configText := string(content)
// Load current preferences
prefs, err := utils.LoadPrefs()
if err != nil {
return fmt.Errorf("failed to load preferences: %v", err)
}
// Check each graphics setting and update preferences
prefs.ReduceTerrainDistance = isConfigSettingCorrect(configText, "farclip", "177")
prefs.SetMultisampleTo2x = isConfigSettingCorrect(configText, "gxMultisample", "2")
prefs.SetShadowLOD0 = isConfigSettingCorrect(configText, "shadowLOD", "0")
// Check libSiliconPatch status (DLL exists and enabled in dlls.txt)
libSiliconPatchPath := filepath.Join(paths.TurtlewowPath, "libSiliconPatch.dll")
dllsTextFile := filepath.Join(paths.TurtlewowPath, "dlls.txt")
libSiliconPatchExists := utils.PathExists(libSiliconPatchPath)
libSiliconPatchEnabled := false
if libSiliconPatchExists && utils.PathExists(dllsTextFile) {
if dllsContent, err := os.ReadFile(dllsTextFile); err == nil {
libSiliconPatchEnabled = strings.Contains(string(dllsContent), "libSiliconPatch.dll")
}
}
prefs.EnableLibSiliconPatch = libSiliconPatchExists && libSiliconPatchEnabled
// Save updated preferences
if err := utils.SavePrefs(prefs); err != nil {
return fmt.Errorf("failed to save preferences: %v", err)
}
debug.Printf("Loaded graphics settings from Config.wtf: terrain=%v, multisample=%v, shadow=%v, libSiliconPatch=%v",
prefs.ReduceTerrainDistance, prefs.SetMultisampleTo2x, prefs.SetShadowLOD0, prefs.EnableLibSiliconPatch)
return nil
}
// CheckGraphicsSettingsPresence checks if libSiliconPatch.dll exists and shadowLOD is applied, updates preferences accordingly
func CheckGraphicsSettingsPresence() {
if paths.TurtlewowPath == "" {
return
}
libSiliconPatchPath := filepath.Join(paths.TurtlewowPath, "libSiliconPatch.dll")
dllsTextFile := filepath.Join(paths.TurtlewowPath, "dlls.txt")
// Check if libSiliconPatch.dll exists
libSiliconPatchExists := utils.PathExists(libSiliconPatchPath)
// Check if it's enabled in dlls.txt
libSiliconPatchEnabled := false
if utils.PathExists(dllsTextFile) {
if fileContentBytes, err := os.ReadFile(dllsTextFile); err == nil {
fileContent := string(fileContentBytes)
libSiliconPatchEnabled = strings.Contains(fileContent, "libSiliconPatch.dll")
}
}
// Check if shadowLOD is currently applied
shadowLODApplied := CheckShadowLODSetting()
// Load current preferences
prefs, _ := utils.LoadPrefs()
// Handle libSiliconPatch preference detection
if libSiliconPatchExists {
if libSiliconPatchEnabled && !prefs.EnableLibSiliconPatch {
// DLL is currently enabled but user preference says disabled - likely first run detection
prefs.EnableLibSiliconPatch = true
debug.Printf("libSiliconPatch detected as enabled, setting user preference to enabled")
} else if !libSiliconPatchEnabled && prefs.EnableLibSiliconPatch {
// DLL exists but not enabled, user preference says enabled - respect user choice
debug.Printf("libSiliconPatch disabled in dlls.txt but user preference is enabled - keeping user preference")
}
}
// Handle shadowLOD preference detection - enable by default if currently applied
if shadowLODApplied && !prefs.SetShadowLOD0 {
// shadowLOD is currently applied but user preference says disabled - likely first run detection
prefs.SetShadowLOD0 = true
debug.Printf("shadowLOD detected as applied, setting user preference to enabled")
} else if !shadowLODApplied && prefs.SetShadowLOD0 {
// shadowLOD not applied but user preference says enabled - respect user choice
debug.Printf("shadowLOD not applied but user preference is enabled - keeping user preference")
}
// Save any changes
utils.SavePrefs(prefs)
debug.Printf("Graphics settings detection: libSiliconPatch exists=%v, enabled_in_dlls=%v, user_setting=%v; shadowLOD applied=%v, user_setting=%v",
libSiliconPatchExists, libSiliconPatchEnabled, prefs.EnableLibSiliconPatch, shadowLODApplied, prefs.SetShadowLOD0)
}
// enableLibSiliconPatchInDlls adds libSiliconPatch.dll to dlls.txt if not present
func enableLibSiliconPatchInDlls() error {
if paths.TurtlewowPath == "" {
return fmt.Errorf("TurtleWoW path not set")
}
dllsTextFile := filepath.Join(paths.TurtlewowPath, "dlls.txt")
libSiliconPatchEntry := "libSiliconPatch.dll"
var fileContentBytes []byte
var err error
if utils.PathExists(dllsTextFile) {
fileContentBytes, err = os.ReadFile(dllsTextFile)
if err != nil {
return fmt.Errorf("failed to read dlls.txt: %v", err)
}
}
currentContent := string(fileContentBytes)
if strings.Contains(currentContent, libSiliconPatchEntry) {
debug.Printf("libSiliconPatch.dll already present in dlls.txt")
return nil
}
// Add libSiliconPatch.dll to dlls.txt
if len(currentContent) > 0 && !strings.HasSuffix(currentContent, "\n") {
currentContent += "\n"
}
currentContent += libSiliconPatchEntry + "\n"
if err := os.WriteFile(dllsTextFile, []byte(currentContent), 0644); err != nil {
return fmt.Errorf("failed to update dlls.txt: %v", err)
}
debug.Printf("Added libSiliconPatch.dll to dlls.txt")
return nil
}
// disableLibSiliconPatchInDlls removes libSiliconPatch.dll from dlls.txt
func disableLibSiliconPatchInDlls() error {
if paths.TurtlewowPath == "" {
return fmt.Errorf("TurtleWoW path not set")
}
dllsTextFile := filepath.Join(paths.TurtlewowPath, "dlls.txt")
if !utils.PathExists(dllsTextFile) {
debug.Printf("dlls.txt not found, nothing to remove")
return nil
}
content, err := os.ReadFile(dllsTextFile)
if err != nil {
return fmt.Errorf("failed to read dlls.txt: %v", err)
}
lines := strings.Split(string(content), "\n")
filteredLines := make([]string, 0, len(lines))
for _, line := range lines {
trimmedLine := strings.TrimSpace(line)
if trimmedLine != "libSiliconPatch.dll" {
filteredLines = append(filteredLines, line)
}
}
updatedContent := strings.Join(filteredLines, "\n")
if err := os.WriteFile(dllsTextFile, []byte(updatedContent), 0644); err != nil {
return fmt.Errorf("failed to update dlls.txt: %v", err)
}
debug.Printf("Removed libSiliconPatch.dll from dlls.txt")
return nil
}