first epoch pass
Some checks failed
Build Go/Fyne App for macOS ARM64 / build (pull_request) Has been cancelled

This commit is contained in:
2025-07-20 21:45:38 -07:00
parent 9b04ad7fd0
commit c735a3f90e
27 changed files with 216 additions and 402 deletions

View File

@@ -65,12 +65,12 @@ jobs:
- name: Verify build output - name: Verify build output
run: | run: |
ls -la TurtleSilicon.app/ ls -la EpochSilicon.app/
ls -la TurtleSilicon.app/Contents/Resources/ ls -la EpochSilicon.app/Contents/Resources/
- name: Upload build artifact - name: Upload build artifact
uses: actions/upload-artifact@v4 uses: actions/upload-artifact@v4
with: with:
name: TurtleSilicon-macos name: EpochSilicon-macos
path: TurtleSilicon.app/ path: EpochSilicon.app/
retention-days: 30 retention-days: 30

6
.gitignore vendored
View File

@@ -1,6 +1,6 @@
.DS_Store .DS_Store
TurtleSilicon.* EpochSilicon.*
TurtleSilicon.app/Contents/MacOS/turtlesilicon EpochSilicon.app/Contents/MacOS/epochsilicon
*.dmg *.dmg
turtlesilicon epochsilicon
.idea .idea

View File

@@ -5,7 +5,7 @@
<key>CFBundleName</key> <key>CFBundleName</key>
<string>EpochSilicon</string> <string>EpochSilicon</string>
<key>CFBundleExecutable</key> <key>CFBundleExecutable</key>
<string>turtlesilicon</string> <string>epochsilicon</string>
<key>CFBundleIdentifier</key> <key>CFBundleIdentifier</key>
<string>com.eburk.epochsilicon</string> <string>com.eburk.epochsilicon</string>
<key>CFBundleIconFile</key> <key>CFBundleIconFile</key>
@@ -17,7 +17,7 @@
<string>MacOSX</string> <string>MacOSX</string>
</array> </array>
<key>CFBundleVersion</key> <key>CFBundleVersion</key>
<string>78</string> <string>91</string>
<key>NSHighResolutionCapable</key> <key>NSHighResolutionCapable</key>
<true/> <true/>
<key>NSSupportsAutomaticGraphicsSwitching</key> <key>NSSupportsAutomaticGraphicsSwitching</key>

View File

@@ -3,4 +3,4 @@
Name = "EpochSilicon" Name = "EpochSilicon"
ID = "com.eburk.epochsilicon" ID = "com.eburk.epochsilicon"
Version = "1.2.4" Version = "1.2.4"
Build = 79 Build = 92

BIN
Icon.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 313 KiB

After

Width:  |  Height:  |  Size: 14 KiB

View File

@@ -7,11 +7,11 @@ all: build-release
build-dev: build-dev:
GOOS=darwin GOARCH=arm64 fyne package GOOS=darwin GOARCH=arm64 fyne package
@echo "Copying additional resources to app bundle..." @echo "Copying additional resources to app bundle..."
@mkdir -p TurtleSilicon.app/Contents/Resources/rosettax87 @mkdir -p EpochSilicon.app/Contents/Resources/rosettax87
@mkdir -p TurtleSilicon.app/Contents/Resources/winerosetta @mkdir -p EpochSilicon.app/Contents/Resources/winerosetta
@cp -R rosettax87/* TurtleSilicon.app/Contents/Resources/rosettax87/ @cp -R rosettax87/* EpochSilicon.app/Contents/Resources/rosettax87/
@cp -R winerosetta/* TurtleSilicon.app/Contents/Resources/winerosetta/ @cp -R winerosetta/* EpochSilicon.app/Contents/Resources/winerosetta/
@cp -R Icon.png TurtleSilicon.app/Contents/Resources/ @cp -R Icon.png EpochSilicon.app/Contents/Resources/
@echo "Development build complete!" @echo "Development build complete!"
build: build-dev build: build-dev
@@ -22,33 +22,33 @@ build-release:
-ldflags="-s -w -X main.appVersion=$$(grep Version FyneApp.toml | cut -d'"' -f2)" \ -ldflags="-s -w -X main.appVersion=$$(grep Version FyneApp.toml | cut -d'"' -f2)" \
-trimpath \ -trimpath \
-tags=release \ -tags=release \
-o turtlesilicon . -o epochsilicon .
@echo "Packaging with fyne..." @echo "Packaging with fyne..."
GOOS=darwin GOARCH=arm64 fyne package --release --executable turtlesilicon GOOS=darwin GOARCH=arm64 fyne package --release --executable epochsilicon
@echo "Copying additional resources to app bundle..." @echo "Copying additional resources to app bundle..."
@mkdir -p TurtleSilicon.app/Contents/Resources/rosettax87 @mkdir -p EpochSilicon.app/Contents/Resources/rosettax87
@mkdir -p TurtleSilicon.app/Contents/Resources/winerosetta @mkdir -p EpochSilicon.app/Contents/Resources/winerosetta
@cp -R rosettax87/* TurtleSilicon.app/Contents/Resources/rosettax87/ @cp -R rosettax87/* EpochSilicon.app/Contents/Resources/rosettax87/
@cp -R winerosetta/* TurtleSilicon.app/Contents/Resources/winerosetta/ @cp -R winerosetta/* EpochSilicon.app/Contents/Resources/winerosetta/
@cp -R Icon.png TurtleSilicon.app/Contents/Resources/ @cp -R Icon.png EpochSilicon.app/Contents/Resources/
@echo "Stripping additional symbols..." @echo "Stripping additional symbols..."
strip -x TurtleSilicon.app/Contents/MacOS/turtlesilicon strip -x EpochSilicon.app/Contents/MacOS/epochsilicon
@echo "Optimized release build complete!" @echo "Optimized release build complete!"
@echo "Binary size: $$(ls -lah TurtleSilicon.app/Contents/MacOS/turtlesilicon | awk '{print $$5}')" @echo "Binary size: $$(ls -lah EpochSilicon.app/Contents/MacOS/epochsilicon | awk '{print $$5}')"
# Clean build artifacts # Clean build artifacts
clean: clean:
rm -rf TurtleSilicon.app rm -rf EpochSilicon.app
rm -f TurtleSilicon.dmg rm -f EpochSilicon.dmg
rm -f turtlesilicon rm -f epochsilicon
dmg: build-release dmg: build-release
@echo "Preparing DMG staging directory..." @echo "Preparing DMG staging directory..."
@rm -rf dmg-staging @rm -rf dmg-staging
@mkdir dmg-staging @mkdir dmg-staging
@cp -R TurtleSilicon.app dmg-staging/ @cp -R EpochSilicon.app dmg-staging/
@ln -s /Applications dmg-staging/Applications @ln -s /Applications dmg-staging/Applications
@echo "Creating DMG file..." @echo "Creating DMG file..."
@hdiutil create -volname TurtleSilicon -srcfolder dmg-staging -ov -format UDZO TurtleSilicon.dmg @hdiutil create -volname EpochSilicon -srcfolder dmg-staging -ov -format UDZO EpochSilicon.dmg
@echo "DMG created: TurtleSilicon.dmg" @echo "DMG created: EpochSilicon.dmg"
@rm -rf dmg-staging @rm -rf dmg-staging

View File

@@ -1,4 +1,4 @@
<h1 align="center"><img src="Icon.png" alt="TurtleSilicon Logo" width="50" height="50" align="center"> TurtleSilicon</h1> <h1 align="center"><img src="Icon.png" alt="EpochSilicon Logo" width="50" height="50" align="center"> EpochSilicon</h1>
<div align="center"> <div align="center">
@@ -11,8 +11,8 @@
<div align="center"> <div align="center">
<img src="img/turtlesilicon-fps_v2.png" alt="Turtle WoW FPS on Apple Silicon" width="49%" /> <img src="img/epochsilicon-fps_v2.png" alt="Turtle WoW FPS on Apple Silicon" width="49%" />
<img src="img/turtlesilicon-app_v4.png" alt="TurtleSilicon Application" width="49%" /> <img src="img/epochsilicon-app_v4.png" alt="TurtleSilicon Application" width="49%" />
</div> </div>
A user-friendly launcher for Turtle WoW on Apple Silicon Macs, with one-click patching of winerosetta, rosettax87 and d9vk. A user-friendly launcher for Turtle WoW on Apple Silicon Macs, with one-click patching of winerosetta, rosettax87 and d9vk.

41
go.mod
View File

@@ -1,46 +1,49 @@
module turtlesilicon module epochsilicon
go 1.21 go 1.24.3
toolchain go1.24.5
require ( require (
fyne.io/fyne/v2 v2.6.1 fyne.io/fyne/v2 v2.6.1
git.burkey.co/eburk/epochcli v0.0.0-20250721041733-516a1f9b570e
github.com/zalando/go-keyring v0.2.6 github.com/zalando/go-keyring v0.2.6
howett.net/plist v1.0.1
) )
require ( require (
al.essio.dev/pkg/shellescape v1.5.1 // indirect al.essio.dev/pkg/shellescape v1.6.0 // indirect
fyne.io/systray v1.11.0 // indirect fyne.io/systray v1.11.0 // indirect
github.com/BurntSushi/toml v1.4.0 // indirect github.com/BurntSushi/toml v1.5.0 // indirect
github.com/danieljoos/wincred v1.2.2 // indirect github.com/danieljoos/wincred v1.2.2 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect github.com/davecgh/go-spew v1.1.1 // indirect
github.com/fredbi/uri v1.1.0 // indirect github.com/fredbi/uri v1.1.0 // indirect
github.com/fsnotify/fsnotify v1.7.0 // indirect github.com/fsnotify/fsnotify v1.9.0 // indirect
github.com/fyne-io/gl-js v0.1.0 // indirect github.com/fyne-io/gl-js v0.2.0 // indirect
github.com/fyne-io/glfw-js v0.2.0 // indirect github.com/fyne-io/glfw-js v0.3.0 // indirect
github.com/fyne-io/image v0.1.1 // indirect github.com/fyne-io/image v0.1.1 // indirect
github.com/fyne-io/oksvg v0.1.0 // indirect github.com/fyne-io/oksvg v0.1.0 // indirect
github.com/go-gl/gl v0.0.0-20231021071112-07e5d0ea2e71 // indirect github.com/go-gl/gl v0.0.0-20231021071112-07e5d0ea2e71 // indirect
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20240506104042-037f3cc74f2a // indirect github.com/go-gl/glfw/v3.3/glfw v0.0.0-20250301202403-da16c1255728 // indirect
github.com/go-text/render v0.2.0 // indirect github.com/go-text/render v0.2.0 // indirect
github.com/go-text/typesetting v0.2.1 // indirect github.com/go-text/typesetting v0.3.0 // indirect
github.com/godbus/dbus/v5 v5.1.0 // indirect github.com/godbus/dbus/v5 v5.1.0 // indirect
github.com/hack-pad/go-indexeddb v0.3.2 // indirect github.com/hack-pad/go-indexeddb v0.3.2 // indirect
github.com/hack-pad/safejs v0.1.0 // indirect github.com/hack-pad/safejs v0.1.1 // indirect
github.com/jeandeaual/go-locale v0.0.0-20241217141322-fcc2cadd6f08 // indirect github.com/jeandeaual/go-locale v0.0.0-20250612000132-0ef82f21eade // indirect
github.com/jsummers/gobmp v0.0.0-20230614200233-a9de23ed2e25 // indirect github.com/jsummers/gobmp v0.0.0-20230614200233-a9de23ed2e25 // indirect
github.com/kr/text v0.2.0 // indirect github.com/kr/text v0.2.0 // indirect
github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646 // indirect github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646 // indirect
github.com/nicksnyder/go-i18n/v2 v2.5.1 // indirect github.com/nicksnyder/go-i18n/v2 v2.6.0 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/rymdport/portal v0.4.1 // indirect github.com/rymdport/portal v0.4.2 // indirect
github.com/srwiley/oksvg v0.0.0-20221011165216-be6e8873101c // indirect github.com/srwiley/oksvg v0.0.0-20221011165216-be6e8873101c // indirect
github.com/srwiley/rasterx v0.0.0-20220730225603-2ab79fcdd4ef // indirect github.com/srwiley/rasterx v0.0.0-20220730225603-2ab79fcdd4ef // indirect
github.com/stretchr/testify v1.10.0 // indirect github.com/stretchr/testify v1.10.0 // indirect
github.com/yuin/goldmark v1.7.8 // indirect github.com/yuin/goldmark v1.7.12 // indirect
golang.org/x/image v0.24.0 // indirect golang.org/x/image v0.29.0 // indirect
golang.org/x/net v0.35.0 // indirect golang.org/x/net v0.42.0 // indirect
golang.org/x/sys v0.30.0 // indirect golang.org/x/sys v0.34.0 // indirect
golang.org/x/text v0.22.0 // indirect golang.org/x/text v0.27.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect
howett.net/plist v1.0.1 // indirect
) )

38
go.sum
View File

@@ -1,11 +1,21 @@
al.essio.dev/pkg/shellescape v1.5.1 h1:86HrALUujYS/h+GtqoB26SBEdkWfmMI6FubjXlsXyho= al.essio.dev/pkg/shellescape v1.5.1 h1:86HrALUujYS/h+GtqoB26SBEdkWfmMI6FubjXlsXyho=
al.essio.dev/pkg/shellescape v1.5.1/go.mod h1:6sIqp7X2P6mThCQ7twERpZTuigpr6KbZWtls1U8I890= al.essio.dev/pkg/shellescape v1.5.1/go.mod h1:6sIqp7X2P6mThCQ7twERpZTuigpr6KbZWtls1U8I890=
al.essio.dev/pkg/shellescape v1.6.0 h1:NxFcEqzFSEVCGN2yq7Huv/9hyCEGVa/TncnOOBBeXHA=
al.essio.dev/pkg/shellescape v1.6.0/go.mod h1:6sIqp7X2P6mThCQ7twERpZTuigpr6KbZWtls1U8I890=
fyne.io/fyne/v2 v2.6.1 h1:kjPJD4/rBS9m2nHJp+npPSuaK79yj6ObMTuzR6VQ1Is= fyne.io/fyne/v2 v2.6.1 h1:kjPJD4/rBS9m2nHJp+npPSuaK79yj6ObMTuzR6VQ1Is=
fyne.io/fyne/v2 v2.6.1/go.mod h1:YZt7SksjvrSNJCwbWFV32WON3mE1Sr7L41D29qMZ/lU= fyne.io/fyne/v2 v2.6.1/go.mod h1:YZt7SksjvrSNJCwbWFV32WON3mE1Sr7L41D29qMZ/lU=
fyne.io/systray v1.11.0 h1:D9HISlxSkx+jHSniMBR6fCFOUjk1x/OOOJLa9lJYAKg= fyne.io/systray v1.11.0 h1:D9HISlxSkx+jHSniMBR6fCFOUjk1x/OOOJLa9lJYAKg=
fyne.io/systray v1.11.0/go.mod h1:RVwqP9nYMo7h5zViCBHri2FgjXF7H2cub7MAq4NSoLs= fyne.io/systray v1.11.0/go.mod h1:RVwqP9nYMo7h5zViCBHri2FgjXF7H2cub7MAq4NSoLs=
git.burkey.co/eburk/epochcli v0.0.0-20250721033741-54cc1d9a552e h1:TiiZEnc7E3/wJ86qHckGoNht0snSUpQyY2cjxRUSs3Q=
git.burkey.co/eburk/epochcli v0.0.0-20250721033741-54cc1d9a552e/go.mod h1:DgybCn9/LpJwvkrsyea9N2nWy/wuDgo6jkpOWYkTH3c=
git.burkey.co/eburk/epochcli v0.0.0-20250721041340-6b6dbdda99e2 h1:89rNJ5p6gYJPZkeJM8nyRHMMgHErfVz8SdLcGiqEyBM=
git.burkey.co/eburk/epochcli v0.0.0-20250721041340-6b6dbdda99e2/go.mod h1:DgybCn9/LpJwvkrsyea9N2nWy/wuDgo6jkpOWYkTH3c=
git.burkey.co/eburk/epochcli v0.0.0-20250721041733-516a1f9b570e h1:WN1jlnC3sc/2ix70bzMPpzsPdsE/pqUIR/Vw8cVEkw8=
git.burkey.co/eburk/epochcli v0.0.0-20250721041733-516a1f9b570e/go.mod h1:DgybCn9/LpJwvkrsyea9N2nWy/wuDgo6jkpOWYkTH3c=
github.com/BurntSushi/toml v1.4.0 h1:kuoIxZQy2WRRk1pttg9asf+WVv6tWQuBNVmK8+nqPr0= github.com/BurntSushi/toml v1.4.0 h1:kuoIxZQy2WRRk1pttg9asf+WVv6tWQuBNVmK8+nqPr0=
github.com/BurntSushi/toml v1.4.0/go.mod h1:ukJfTF/6rtPPRCnwkur4qwRxa8vTRFBF0uk2lLoLwho= github.com/BurntSushi/toml v1.4.0/go.mod h1:ukJfTF/6rtPPRCnwkur4qwRxa8vTRFBF0uk2lLoLwho=
github.com/BurntSushi/toml v1.5.0 h1:W5quZX/G/csjUnuI8SUYlsHs9M38FC7znL0lIO+DvMg=
github.com/BurntSushi/toml v1.5.0/go.mod h1:ukJfTF/6rtPPRCnwkur4qwRxa8vTRFBF0uk2lLoLwho=
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
github.com/danieljoos/wincred v1.2.2 h1:774zMFJrqaeYCK2W57BgAem/MLi6mtSE47MB6BOJ0i0= github.com/danieljoos/wincred v1.2.2 h1:774zMFJrqaeYCK2W57BgAem/MLi6mtSE47MB6BOJ0i0=
github.com/danieljoos/wincred v1.2.2/go.mod h1:w7w4Utbrz8lqeMbDAK0lkNJUv5sAOkFi7nd/ogr0Uh8= github.com/danieljoos/wincred v1.2.2/go.mod h1:w7w4Utbrz8lqeMbDAK0lkNJUv5sAOkFi7nd/ogr0Uh8=
@@ -17,10 +27,16 @@ github.com/fredbi/uri v1.1.0 h1:OqLpTXtyRg9ABReqvDGdJPqZUxs8cyBDOMXBbskCaB8=
github.com/fredbi/uri v1.1.0/go.mod h1:aYTUoAXBOq7BLfVJ8GnKmfcuURosB1xyHDIfWeC/iW4= github.com/fredbi/uri v1.1.0/go.mod h1:aYTUoAXBOq7BLfVJ8GnKmfcuURosB1xyHDIfWeC/iW4=
github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA= github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA=
github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM= github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM=
github.com/fsnotify/fsnotify v1.9.0 h1:2Ml+OJNzbYCTzsxtv8vKSFD9PbJjmhYF14k/jKC7S9k=
github.com/fsnotify/fsnotify v1.9.0/go.mod h1:8jBTzvmWwFyi3Pb8djgCCO5IBqzKJ/Jwo8TRcHyHii0=
github.com/fyne-io/gl-js v0.1.0 h1:8luJzNs0ntEAJo+8x8kfUOXujUlP8gB3QMOxO2mUdpM= github.com/fyne-io/gl-js v0.1.0 h1:8luJzNs0ntEAJo+8x8kfUOXujUlP8gB3QMOxO2mUdpM=
github.com/fyne-io/gl-js v0.1.0/go.mod h1:ZcepK8vmOYLu96JoxbCKJy2ybr+g1pTnaBDdl7c3ajI= github.com/fyne-io/gl-js v0.1.0/go.mod h1:ZcepK8vmOYLu96JoxbCKJy2ybr+g1pTnaBDdl7c3ajI=
github.com/fyne-io/gl-js v0.2.0 h1:+EXMLVEa18EfkXBVKhifYB6OGs3HwKO3lUElA0LlAjs=
github.com/fyne-io/gl-js v0.2.0/go.mod h1:ZcepK8vmOYLu96JoxbCKJy2ybr+g1pTnaBDdl7c3ajI=
github.com/fyne-io/glfw-js v0.2.0 h1:8GUZtN2aCoTPNqgRDxK5+kn9OURINhBEBc7M4O1KrmM= github.com/fyne-io/glfw-js v0.2.0 h1:8GUZtN2aCoTPNqgRDxK5+kn9OURINhBEBc7M4O1KrmM=
github.com/fyne-io/glfw-js v0.2.0/go.mod h1:Ri6te7rdZtBgBpxLW19uBpp3Dl6K9K/bRaYdJ22G8Jk= github.com/fyne-io/glfw-js v0.2.0/go.mod h1:Ri6te7rdZtBgBpxLW19uBpp3Dl6K9K/bRaYdJ22G8Jk=
github.com/fyne-io/glfw-js v0.3.0 h1:d8k2+Y7l+zy2pc7wlGRyPfTgZoqDf3AI4G+2zOWhWUk=
github.com/fyne-io/glfw-js v0.3.0/go.mod h1:Ri6te7rdZtBgBpxLW19uBpp3Dl6K9K/bRaYdJ22G8Jk=
github.com/fyne-io/image v0.1.1 h1:WH0z4H7qfvNUw5l4p3bC1q70sa5+YWVt6HCj7y4VNyA= github.com/fyne-io/image v0.1.1 h1:WH0z4H7qfvNUw5l4p3bC1q70sa5+YWVt6HCj7y4VNyA=
github.com/fyne-io/image v0.1.1/go.mod h1:xrfYBh6yspc+KjkgdZU/ifUC9sPA5Iv7WYUBzQKK7JM= github.com/fyne-io/image v0.1.1/go.mod h1:xrfYBh6yspc+KjkgdZU/ifUC9sPA5Iv7WYUBzQKK7JM=
github.com/fyne-io/oksvg v0.1.0 h1:7EUKk3HV3Y2E+qypp3nWqMXD7mum0hCw2KEGhI1fnBw= github.com/fyne-io/oksvg v0.1.0 h1:7EUKk3HV3Y2E+qypp3nWqMXD7mum0hCw2KEGhI1fnBw=
@@ -29,10 +45,14 @@ github.com/go-gl/gl v0.0.0-20231021071112-07e5d0ea2e71 h1:5BVwOaUSBTlVZowGO6VZGw
github.com/go-gl/gl v0.0.0-20231021071112-07e5d0ea2e71/go.mod h1:9YTyiznxEY1fVinfM7RvRcjRHbw2xLBJ3AAGIT0I4Nw= github.com/go-gl/gl v0.0.0-20231021071112-07e5d0ea2e71/go.mod h1:9YTyiznxEY1fVinfM7RvRcjRHbw2xLBJ3AAGIT0I4Nw=
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20240506104042-037f3cc74f2a h1:vxnBhFDDT+xzxf1jTJKMKZw3H0swfWk9RpWbBbDK5+0= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20240506104042-037f3cc74f2a h1:vxnBhFDDT+xzxf1jTJKMKZw3H0swfWk9RpWbBbDK5+0=
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20240506104042-037f3cc74f2a/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20240506104042-037f3cc74f2a/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20250301202403-da16c1255728 h1:RkGhqHxEVAvPM0/R+8g7XRwQnHatO0KAuVcwHo8q9W8=
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20250301202403-da16c1255728/go.mod h1:SyRD8YfuKk+ZXlDqYiqe1qMSqjNgtHzBTG810KUagMc=
github.com/go-text/render v0.2.0 h1:LBYoTmp5jYiJ4NPqDc2pz17MLmA3wHw1dZSVGcOdeAc= github.com/go-text/render v0.2.0 h1:LBYoTmp5jYiJ4NPqDc2pz17MLmA3wHw1dZSVGcOdeAc=
github.com/go-text/render v0.2.0/go.mod h1:CkiqfukRGKJA5vZZISkjSYrcdtgKQWRa2HIzvwNN5SU= github.com/go-text/render v0.2.0/go.mod h1:CkiqfukRGKJA5vZZISkjSYrcdtgKQWRa2HIzvwNN5SU=
github.com/go-text/typesetting v0.2.1 h1:x0jMOGyO3d1qFAPI0j4GSsh7M0Q3Ypjzr4+CEVg82V8= github.com/go-text/typesetting v0.2.1 h1:x0jMOGyO3d1qFAPI0j4GSsh7M0Q3Ypjzr4+CEVg82V8=
github.com/go-text/typesetting v0.2.1/go.mod h1:mTOxEwasOFpAMBjEQDhdWRckoLLeI/+qrQeBCTGEt6M= github.com/go-text/typesetting v0.2.1/go.mod h1:mTOxEwasOFpAMBjEQDhdWRckoLLeI/+qrQeBCTGEt6M=
github.com/go-text/typesetting v0.3.0 h1:OWCgYpp8njoxSRpwrdd1bQOxdjOXDj9Rqart9ML4iF4=
github.com/go-text/typesetting v0.3.0/go.mod h1:qjZLkhRgOEYMhU9eHBr3AR4sfnGJvOXNLt8yRAySFuY=
github.com/go-text/typesetting-utils v0.0.0-20241103174707-87a29e9e6066 h1:qCuYC+94v2xrb1PoS4NIDe7DGYtLnU2wWiQe9a1B1c0= github.com/go-text/typesetting-utils v0.0.0-20241103174707-87a29e9e6066 h1:qCuYC+94v2xrb1PoS4NIDe7DGYtLnU2wWiQe9a1B1c0=
github.com/go-text/typesetting-utils v0.0.0-20241103174707-87a29e9e6066/go.mod h1:DDxDdQEnB70R8owOx3LVpEFvpMK9eeH1o2r0yZhFI9o= github.com/go-text/typesetting-utils v0.0.0-20241103174707-87a29e9e6066/go.mod h1:DDxDdQEnB70R8owOx3LVpEFvpMK9eeH1o2r0yZhFI9o=
github.com/godbus/dbus/v5 v5.1.0 h1:4KLkAxT3aOY8Li4FRJe/KvhoNFFxo0m6fNuFUO8QJUk= github.com/godbus/dbus/v5 v5.1.0 h1:4KLkAxT3aOY8Li4FRJe/KvhoNFFxo0m6fNuFUO8QJUk=
@@ -45,8 +65,12 @@ github.com/hack-pad/go-indexeddb v0.3.2 h1:DTqeJJYc1usa45Q5r52t01KhvlSN02+Oq+tQb
github.com/hack-pad/go-indexeddb v0.3.2/go.mod h1:QvfTevpDVlkfomY498LhstjwbPW6QC4VC/lxYb0Kom0= github.com/hack-pad/go-indexeddb v0.3.2/go.mod h1:QvfTevpDVlkfomY498LhstjwbPW6QC4VC/lxYb0Kom0=
github.com/hack-pad/safejs v0.1.0 h1:qPS6vjreAqh2amUqj4WNG1zIw7qlRQJ9K10eDKMCnE8= github.com/hack-pad/safejs v0.1.0 h1:qPS6vjreAqh2amUqj4WNG1zIw7qlRQJ9K10eDKMCnE8=
github.com/hack-pad/safejs v0.1.0/go.mod h1:HdS+bKF1NrE72VoXZeWzxFOVQVUSqZJAG0xNCnb+Tio= github.com/hack-pad/safejs v0.1.0/go.mod h1:HdS+bKF1NrE72VoXZeWzxFOVQVUSqZJAG0xNCnb+Tio=
github.com/hack-pad/safejs v0.1.1 h1:d5qPO0iQ7h2oVtpzGnLExE+Wn9AtytxIfltcS2b9KD8=
github.com/hack-pad/safejs v0.1.1/go.mod h1:HdS+bKF1NrE72VoXZeWzxFOVQVUSqZJAG0xNCnb+Tio=
github.com/jeandeaual/go-locale v0.0.0-20241217141322-fcc2cadd6f08 h1:wMeVzrPO3mfHIWLZtDcSaGAe2I4PW9B/P5nMkRSwCAc= github.com/jeandeaual/go-locale v0.0.0-20241217141322-fcc2cadd6f08 h1:wMeVzrPO3mfHIWLZtDcSaGAe2I4PW9B/P5nMkRSwCAc=
github.com/jeandeaual/go-locale v0.0.0-20241217141322-fcc2cadd6f08/go.mod h1:ZDXo8KHryOWSIqnsb/CiDq7hQUYryCgdVnxbj8tDG7o= github.com/jeandeaual/go-locale v0.0.0-20241217141322-fcc2cadd6f08/go.mod h1:ZDXo8KHryOWSIqnsb/CiDq7hQUYryCgdVnxbj8tDG7o=
github.com/jeandeaual/go-locale v0.0.0-20250612000132-0ef82f21eade h1:FmusiCI1wHw+XQbvL9M+1r/C3SPqKrmBaIOYwVfQoDE=
github.com/jeandeaual/go-locale v0.0.0-20250612000132-0ef82f21eade/go.mod h1:ZDXo8KHryOWSIqnsb/CiDq7hQUYryCgdVnxbj8tDG7o=
github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI=
github.com/jsummers/gobmp v0.0.0-20230614200233-a9de23ed2e25 h1:YLvr1eE6cdCqjOe972w/cYF+FjW34v27+9Vo5106B4M= github.com/jsummers/gobmp v0.0.0-20230614200233-a9de23ed2e25 h1:YLvr1eE6cdCqjOe972w/cYF+FjW34v27+9Vo5106B4M=
github.com/jsummers/gobmp v0.0.0-20230614200233-a9de23ed2e25/go.mod h1:kLgvv7o6UM+0QSf0QjAse3wReFDsb9qbZJdfexWlrQw= github.com/jsummers/gobmp v0.0.0-20230614200233-a9de23ed2e25/go.mod h1:kLgvv7o6UM+0QSf0QjAse3wReFDsb9qbZJdfexWlrQw=
@@ -56,6 +80,8 @@ github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646 h1:zYyBkD/k9seD2A7fsi6
github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646/go.mod h1:jpp1/29i3P1S/RLdc7JQKbRpFeM1dOBd8T9ki5s+AY8= github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646/go.mod h1:jpp1/29i3P1S/RLdc7JQKbRpFeM1dOBd8T9ki5s+AY8=
github.com/nicksnyder/go-i18n/v2 v2.5.1 h1:IxtPxYsR9Gp60cGXjfuR/llTqV8aYMsC472zD0D1vHk= github.com/nicksnyder/go-i18n/v2 v2.5.1 h1:IxtPxYsR9Gp60cGXjfuR/llTqV8aYMsC472zD0D1vHk=
github.com/nicksnyder/go-i18n/v2 v2.5.1/go.mod h1:DrhgsSDZxoAfvVrBVLXoxZn/pN5TXqaDbq7ju94viiQ= github.com/nicksnyder/go-i18n/v2 v2.5.1/go.mod h1:DrhgsSDZxoAfvVrBVLXoxZn/pN5TXqaDbq7ju94viiQ=
github.com/nicksnyder/go-i18n/v2 v2.6.0 h1:C/m2NNWNiTB6SK4Ao8df5EWm3JETSTIGNXBpMJTxzxQ=
github.com/nicksnyder/go-i18n/v2 v2.6.0/go.mod h1:88sRqr0C6OPyJn0/KRNaEz1uWorjxIKP7rUUcvycecE=
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs= github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs=
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
github.com/pkg/profile v1.7.0 h1:hnbDkaNWPCLMO9wGLdBFTIZvzDrDfBM2072E1S9gJkA= github.com/pkg/profile v1.7.0 h1:hnbDkaNWPCLMO9wGLdBFTIZvzDrDfBM2072E1S9gJkA=
@@ -64,6 +90,8 @@ github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZb
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/rymdport/portal v0.4.1 h1:2dnZhjf5uEaeDjeF/yBIeeRo6pNI2QAKm7kq1w/kbnA= github.com/rymdport/portal v0.4.1 h1:2dnZhjf5uEaeDjeF/yBIeeRo6pNI2QAKm7kq1w/kbnA=
github.com/rymdport/portal v0.4.1/go.mod h1:kFF4jslnJ8pD5uCi17brj/ODlfIidOxlgUDTO5ncnC4= github.com/rymdport/portal v0.4.1/go.mod h1:kFF4jslnJ8pD5uCi17brj/ODlfIidOxlgUDTO5ncnC4=
github.com/rymdport/portal v0.4.2 h1:7jKRSemwlTyVHHrTGgQg7gmNPJs88xkbKcIL3NlcmSU=
github.com/rymdport/portal v0.4.2/go.mod h1:kFF4jslnJ8pD5uCi17brj/ODlfIidOxlgUDTO5ncnC4=
github.com/srwiley/oksvg v0.0.0-20221011165216-be6e8873101c h1:km8GpoQut05eY3GiYWEedbTT0qnSxrCjsVbb7yKY1KE= github.com/srwiley/oksvg v0.0.0-20221011165216-be6e8873101c h1:km8GpoQut05eY3GiYWEedbTT0qnSxrCjsVbb7yKY1KE=
github.com/srwiley/oksvg v0.0.0-20221011165216-be6e8873101c/go.mod h1:cNQ3dwVJtS5Hmnjxy6AgTPd0Inb3pW05ftPSX7NZO7Q= github.com/srwiley/oksvg v0.0.0-20221011165216-be6e8873101c/go.mod h1:cNQ3dwVJtS5Hmnjxy6AgTPd0Inb3pW05ftPSX7NZO7Q=
github.com/srwiley/rasterx v0.0.0-20220730225603-2ab79fcdd4ef h1:Ch6Q+AZUxDBCVqdkI8FSpFyZDtCVBc2VmejdNrm5rRQ= github.com/srwiley/rasterx v0.0.0-20220730225603-2ab79fcdd4ef h1:Ch6Q+AZUxDBCVqdkI8FSpFyZDtCVBc2VmejdNrm5rRQ=
@@ -74,16 +102,26 @@ github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOf
github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
github.com/yuin/goldmark v1.7.8 h1:iERMLn0/QJeHFhxSt3p6PeN9mGnvIKSpG9YYorDMnic= github.com/yuin/goldmark v1.7.8 h1:iERMLn0/QJeHFhxSt3p6PeN9mGnvIKSpG9YYorDMnic=
github.com/yuin/goldmark v1.7.8/go.mod h1:uzxRWxtg69N339t3louHJ7+O03ezfj6PlliRlaOzY1E= github.com/yuin/goldmark v1.7.8/go.mod h1:uzxRWxtg69N339t3louHJ7+O03ezfj6PlliRlaOzY1E=
github.com/yuin/goldmark v1.7.12 h1:YwGP/rrea2/CnCtUHgjuolG/PnMxdQtPMO5PvaE2/nY=
github.com/yuin/goldmark v1.7.12/go.mod h1:ip/1k0VRfGynBgxOz0yCqHrbZXhcjxyuS66Brc7iBKg=
github.com/zalando/go-keyring v0.2.6 h1:r7Yc3+H+Ux0+M72zacZoItR3UDxeWfKTcabvkI8ua9s= github.com/zalando/go-keyring v0.2.6 h1:r7Yc3+H+Ux0+M72zacZoItR3UDxeWfKTcabvkI8ua9s=
github.com/zalando/go-keyring v0.2.6/go.mod h1:2TCrxYrbUNYfNS/Kgy/LSrkSQzZ5UPVH85RwfczwvcI= github.com/zalando/go-keyring v0.2.6/go.mod h1:2TCrxYrbUNYfNS/Kgy/LSrkSQzZ5UPVH85RwfczwvcI=
golang.org/x/image v0.24.0 h1:AN7zRgVsbvmTfNyqIbbOraYL8mSwcKncEj8ofjgzcMQ= golang.org/x/image v0.24.0 h1:AN7zRgVsbvmTfNyqIbbOraYL8mSwcKncEj8ofjgzcMQ=
golang.org/x/image v0.24.0/go.mod h1:4b/ITuLfqYq1hqZcjofwctIhi7sZh2WaCjvsBNjjya8= golang.org/x/image v0.24.0/go.mod h1:4b/ITuLfqYq1hqZcjofwctIhi7sZh2WaCjvsBNjjya8=
golang.org/x/image v0.29.0 h1:HcdsyR4Gsuys/Axh0rDEmlBmB68rW1U9BUdB3UVHsas=
golang.org/x/image v0.29.0/go.mod h1:RVJROnf3SLK8d26OW91j4FrIHGbsJ8QnbEocVTOWQDA=
golang.org/x/net v0.35.0 h1:T5GQRQb2y08kTAByq9L4/bz8cipCdA8FbRTXewonqY8= golang.org/x/net v0.35.0 h1:T5GQRQb2y08kTAByq9L4/bz8cipCdA8FbRTXewonqY8=
golang.org/x/net v0.35.0/go.mod h1:EglIi67kWsHKlRzzVMUD93VMSWGFOMSZgxFjparz1Qk= golang.org/x/net v0.35.0/go.mod h1:EglIi67kWsHKlRzzVMUD93VMSWGFOMSZgxFjparz1Qk=
golang.org/x/net v0.42.0 h1:jzkYrhi3YQWD6MLBJcsklgQsoAcw89EcZbJw8Z614hs=
golang.org/x/net v0.42.0/go.mod h1:FF1RA5d3u7nAYA4z2TkclSCKh68eSXtiFwcWQpPXdt8=
golang.org/x/sys v0.30.0 h1:QjkSwP/36a20jFYWkSue1YwXzLmsV5Gfq7Eiy72C1uc= golang.org/x/sys v0.30.0 h1:QjkSwP/36a20jFYWkSue1YwXzLmsV5Gfq7Eiy72C1uc=
golang.org/x/sys v0.30.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.30.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.34.0 h1:H5Y5sJ2L2JRdyv7ROF1he/lPdvFsd0mJHFw2ThKHxLA=
golang.org/x/sys v0.34.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
golang.org/x/text v0.22.0 h1:bofq7m3/HAFvbF51jz3Q9wLg3jkvSPuiZu/pD1XwgtM= golang.org/x/text v0.22.0 h1:bofq7m3/HAFvbF51jz3Q9wLg3jkvSPuiZu/pD1XwgtM=
golang.org/x/text v0.22.0/go.mod h1:YRoo4H8PVmsu+E3Ou7cqLVH8oXWIHVoX0jqUWALQhfY= golang.org/x/text v0.22.0/go.mod h1:YRoo4H8PVmsu+E3Ou7cqLVH8oXWIHVoX0jqUWALQhfY=
golang.org/x/text v0.27.0 h1:4fGWRpyh641NLlecmyl4LOe6yDdfaYNrGb2zdfo4JV4=
golang.org/x/text v0.27.0/go.mod h1:1D28KMCvyooCX9hBiosv5Tz/+YLxj0j7XhWjpSUF7CU=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f h1:BLraFXnmrev5lT+xlilqcH8XK9/i0At2xKjWk4p6zsU= gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f h1:BLraFXnmrev5lT+xlilqcH8XK9/i0At2xKjWk4p6zsU=
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=

View File

@@ -1,11 +1,11 @@
package main package main
import ( import (
"epochsilicon/pkg/debug"
"epochsilicon/pkg/service"
"epochsilicon/pkg/ui"
"fyne.io/fyne/v2" "fyne.io/fyne/v2"
"fyne.io/fyne/v2/app" "fyne.io/fyne/v2/app"
"turtlesilicon/pkg/debug"
"turtlesilicon/pkg/service"
"turtlesilicon/pkg/ui"
) )
const appVersion = "0.1.0" const appVersion = "0.1.0"

View File

@@ -8,9 +8,9 @@ import (
"path/filepath" "path/filepath"
"sync" "sync"
"turtlesilicon/pkg/debug" "epochsilicon/pkg/debug"
"turtlesilicon/pkg/paths" // Corrected import path "epochsilicon/pkg/paths" // Corrected import path
"turtlesilicon/pkg/utils" // Corrected import path "epochsilicon/pkg/utils" // Corrected import path
"fyne.io/fyne/v2" "fyne.io/fyne/v2"
"fyne.io/fyne/v2/dialog" "fyne.io/fyne/v2/dialog"
@@ -110,7 +110,7 @@ func LaunchGame(myWindow fyne.Window) {
return return
} }
if paths.EpochPath == "" { if paths.EpochPath == "" {
dialog.ShowError(fmt.Errorf("TurtleWoW path not set. Please set it in the patcher."), myWindow) dialog.ShowError(fmt.Errorf("Epoch path not set. Please set it in the patcher."), myWindow)
return return
} }
if !paths.PatchesAppliedEpoch || !paths.PatchesAppliedCrossOver { if !paths.PatchesAppliedEpoch || !paths.PatchesAppliedCrossOver {
@@ -132,28 +132,9 @@ func LaunchGame(myWindow fyne.Window) {
} }
gameMutex.Unlock() gameMutex.Unlock()
debug.Println("Preparing to launch TurtleSilicon...") debug.Println("Preparing to launch EpochSilicon...")
// Determine which WoW executable to use based on vanilla-tweaks preference wowExePath := filepath.Join(paths.EpochPath, "Project-Epoch.exe")
var wowExePath string
if EnableVanillaTweaks {
if !CheckForWoWTweakedExecutable() {
// Show dialog asking if user wants us to apply vanilla-tweaks
HandleVanillaTweaksRequest(myWindow, func() {
// After successful patching, continue with launch using the tweaked executable
wowTweakedExePath := GetWoWTweakedExecutablePath()
if wowTweakedExePath != "" {
continueLaunch(myWindow, wowTweakedExePath)
} else {
dialog.ShowError(fmt.Errorf("failed to find WoW-tweaked.exe after patching"), myWindow)
}
})
return // Exit early since dialog will handle the continuation
}
wowExePath = GetWoWTweakedExecutablePath()
} else {
wowExePath = filepath.Join(paths.EpochPath, "WoW.exe")
}
// Continue with normal launch process // Continue with normal launch process
continueLaunch(myWindow, wowExePath) continueLaunch(myWindow, wowExePath)
@@ -161,12 +142,12 @@ func LaunchGame(myWindow fyne.Window) {
// continueLaunch continues the game launch process with the specified executable // continueLaunch continues the game launch process with the specified executable
func continueLaunch(myWindow fyne.Window, wowExePath string) { func continueLaunch(myWindow fyne.Window, wowExePath string) {
rosettaInTurtlePath := filepath.Join(paths.EpochPath, "rosettax87") rosettaInEpochPath := filepath.Join(paths.EpochPath, "rosettax87")
rosettaExecutable := filepath.Join(rosettaInTurtlePath, "rosettax87") rosettaExecutable := filepath.Join(rosettaInEpochPath, "rosettax87")
wineloader2Path := filepath.Join(paths.CrossoverPath, "Contents", "SharedSupport", "CrossOver", "CrossOver-Hosted Application", "wineloader2") wineloader2Path := filepath.Join(paths.CrossoverPath, "Contents", "SharedSupport", "CrossOver", "CrossOver-Hosted Application", "wineloader2")
if !utils.PathExists(rosettaExecutable) { if !utils.PathExists(rosettaExecutable) {
dialog.ShowError(fmt.Errorf("rosetta executable not found at %s. Ensure TurtleWoW patching was successful", rosettaExecutable), myWindow) dialog.ShowError(fmt.Errorf("rosetta executable not found at %s. Ensure Epoch patching was successful", rosettaExecutable), myWindow)
return return
} }
if !utils.PathExists(wineloader2Path) { if !utils.PathExists(wineloader2Path) {
@@ -174,7 +155,7 @@ func continueLaunch(myWindow fyne.Window, wowExePath string) {
return return
} }
if !utils.PathExists(wowExePath) { if !utils.PathExists(wowExePath) {
dialog.ShowError(fmt.Errorf("WoW executable not found at %s. Ensure your TurtleWoW directory is correct", wowExePath), myWindow) dialog.ShowError(fmt.Errorf("WoW executable not found at %s. Ensure your Epoch directory is correct", wowExePath), myWindow)
return return
} }
@@ -198,7 +179,7 @@ func continueLaunch(myWindow fyne.Window, wowExePath string) {
debug.Println("RosettaX87 service is running. Proceeding to launch WoW.") debug.Println("RosettaX87 service is running. Proceeding to launch WoW.")
if paths.CrossoverPath == "" || paths.EpochPath == "" { if paths.CrossoverPath == "" || paths.EpochPath == "" {
dialog.ShowError(fmt.Errorf("CrossOver path or TurtleWoW path is not set. Cannot launch WoW."), myWindow) dialog.ShowError(fmt.Errorf("CrossOver path or Epoch path is not set. Cannot launch WoW."), myWindow)
return return
} }

View File

@@ -7,8 +7,8 @@ import (
"regexp" "regexp"
"strings" "strings"
"turtlesilicon/pkg/debug" "epochsilicon/pkg/debug"
"turtlesilicon/pkg/paths" "epochsilicon/pkg/paths"
) )
// RecommendedSettings contains the recommended graphics settings for optimal performance // RecommendedSettings contains the recommended graphics settings for optimal performance
@@ -25,7 +25,7 @@ var RecommendedSettings = map[string]string{
// Returns true if all settings are correctly applied, false otherwise // Returns true if all settings are correctly applied, false otherwise
func CheckRecommendedSettings() bool { func CheckRecommendedSettings() bool {
if paths.EpochPath == "" { if paths.EpochPath == "" {
debug.Printf("TurtleWoW path not set, cannot check Config.wtf") debug.Printf("Epoch path not set, cannot check Config.wtf")
return false return false
} }
@@ -74,7 +74,7 @@ func isSettingCorrect(configText, setting, expectedValue string) bool {
// ApplyRecommendedSettings applies all recommended graphics settings to Config.wtf // ApplyRecommendedSettings applies all recommended graphics settings to Config.wtf
func ApplyRecommendedSettings() error { func ApplyRecommendedSettings() error {
if paths.EpochPath == "" { if paths.EpochPath == "" {
return fmt.Errorf("TurtleWoW path not set") return fmt.Errorf("Epoch path not set")
} }
configPath := filepath.Join(paths.EpochPath, "WTF", "Config.wtf") configPath := filepath.Join(paths.EpochPath, "WTF", "Config.wtf")

View File

@@ -1,205 +0,0 @@
package launcher
import (
"fmt"
"os"
"os/exec"
"path/filepath"
"turtlesilicon/pkg/debug"
"turtlesilicon/pkg/paths"
"turtlesilicon/pkg/utils"
"fyne.io/fyne/v2"
"fyne.io/fyne/v2/dialog"
)
// ApplyVanillaTweaks applies vanilla-tweaks to WoW.exe to create WoW-tweaked.exe
func ApplyVanillaTweaks(myWindow fyne.Window) error {
if paths.EpochPath == "" {
return fmt.Errorf("TurtleWoW path not set")
}
if paths.CrossoverPath == "" {
return fmt.Errorf("CrossOver path not set")
}
// Get the current working directory (where the app executable is located)
execPath, err := os.Executable()
if err != nil {
return fmt.Errorf("failed to get executable path: %v", err)
}
appDir := filepath.Dir(execPath)
// Check if we're in development mode
vanillaTweaksPath := filepath.Join(appDir, "winerosetta", "vanilla-tweaks.exe")
if !utils.PathExists(vanillaTweaksPath) {
// Try relative path from current working directory (for development)
workingDir, _ := os.Getwd()
vanillaTweaksPath = filepath.Join(workingDir, "winerosetta", "vanilla-tweaks.exe")
if !utils.PathExists(vanillaTweaksPath) {
return fmt.Errorf("vanilla-tweaks.exe not found")
}
}
wowExePath := filepath.Join(paths.EpochPath, "WoW.exe")
wineloader2Path := filepath.Join(paths.CrossoverPath, "Contents", "SharedSupport", "CrossOver", "CrossOver-Hosted Application", "wineloader2")
if !utils.PathExists(wowExePath) {
return fmt.Errorf("WoW.exe not found at %s", wowExePath)
}
if !utils.PathExists(wineloader2Path) {
return fmt.Errorf("wineloader2 not found at %s", wineloader2Path)
}
// First, copy vanilla-tweaks.exe to the TurtleWoW directory temporarily
tempVanillaTweaksPath := filepath.Join(paths.EpochPath, "vanilla-tweaks.exe")
// Copy vanilla-tweaks.exe to TurtleWoW directory
debug.Printf("Copying vanilla-tweaks.exe from %s to %s", vanillaTweaksPath, tempVanillaTweaksPath)
sourceFile, err := os.Open(vanillaTweaksPath)
if err != nil {
return fmt.Errorf("failed to open vanilla-tweaks.exe: %v", err)
}
defer sourceFile.Close()
destFile, err := os.Create(tempVanillaTweaksPath)
if err != nil {
return fmt.Errorf("failed to create temporary vanilla-tweaks.exe: %v", err)
}
defer destFile.Close()
_, err = destFile.ReadFrom(sourceFile)
if err != nil {
return fmt.Errorf("failed to copy vanilla-tweaks.exe: %v", err)
}
// Ensure the copied file is executable
if err := os.Chmod(tempVanillaTweaksPath, 0755); err != nil {
debug.Printf("Warning: failed to set executable permission on vanilla-tweaks.exe: %v", err)
}
// Build the command to apply vanilla-tweaks using the correct format:
// cd "path" && "wineloader2" ./vanilla-tweaks.exe --no-frilldistance -no-farclip ./WoW.exe
shellCmd := fmt.Sprintf(`cd %s && %s ./vanilla-tweaks.exe --no-frilldistance --no-farclip ./WoW.exe`,
utils.QuotePathForShell(paths.EpochPath),
utils.QuotePathForShell(wineloader2Path))
debug.Printf("Applying vanilla-tweaks with command: %s", shellCmd)
// Execute the command
cmd := exec.Command("sh", "-c", shellCmd)
output, err := cmd.CombinedOutput()
debug.Printf("vanilla-tweaks command output: %s", string(output))
// Clean up the temporary vanilla-tweaks.exe file
if cleanupErr := os.Remove(tempVanillaTweaksPath); cleanupErr != nil {
debug.Printf("Warning: failed to clean up temporary vanilla-tweaks.exe: %v", cleanupErr)
}
// Always check if the output file was created, regardless of exit code
// Some Wine programs report error exit codes even when they succeed
foundPath := GetWoWTweakedExecutablePath()
if foundPath == "" {
// Only report error if no output file was created
if err != nil {
debug.Printf("vanilla-tweaks command failed: %v", err)
return fmt.Errorf("failed to apply vanilla-tweaks: %v\nOutput: %s", err, string(output))
} else {
return fmt.Errorf("vanilla-tweaks completed but WoW-tweaked.exe was not created\nOutput: %s", string(output))
}
}
// If we found the file but there was an error code, log it as a warning
if err != nil {
debug.Printf("vanilla-tweaks reported error but output file was created: %v", err)
}
debug.Println("vanilla-tweaks applied successfully")
return nil
}
// CheckForVanillaTweaksExecutable checks if vanilla-tweaks.exe exists and is accessible
func CheckForVanillaTweaksExecutable() bool {
// Get the current working directory (where the app executable is located)
execPath, err := os.Executable()
if err != nil {
return false
}
appDir := filepath.Dir(execPath)
// Check if we're in development mode (running from VSCode)
vanillaTweaksPath := filepath.Join(appDir, "winerosetta", "vanilla-tweaks.exe")
if utils.PathExists(vanillaTweaksPath) {
return true
}
// Try relative path from current working directory (for development)
workingDir, _ := os.Getwd()
vanillaTweaksPath = filepath.Join(workingDir, "winerosetta", "vanilla-tweaks.exe")
return utils.PathExists(vanillaTweaksPath)
}
// GetVanillaTweaksExecutablePath returns the path to vanilla-tweaks.exe if it exists
func GetVanillaTweaksExecutablePath() (string, error) {
// Get the current working directory (where the app executable is located)
execPath, err := os.Executable()
if err != nil {
return "", fmt.Errorf("failed to get executable path: %v", err)
}
appDir := filepath.Dir(execPath)
// Check if we're in development mode (running from VSCode)
vanillaTweaksPath := filepath.Join(appDir, "winerosetta", "vanilla-tweaks.exe")
if utils.PathExists(vanillaTweaksPath) {
return vanillaTweaksPath, nil
}
// Try relative path from current working directory (for development)
workingDir, _ := os.Getwd()
vanillaTweaksPath = filepath.Join(workingDir, "winerosetta", "vanilla-tweaks.exe")
if utils.PathExists(vanillaTweaksPath) {
return vanillaTweaksPath, nil
}
return "", fmt.Errorf("vanilla-tweaks.exe not found")
}
// CheckForWoWTweakedExecutable checks if WoW_tweaked.exe exists in the TurtleWoW directory
func CheckForWoWTweakedExecutable() bool {
if paths.EpochPath == "" {
return false
}
testPath := filepath.Join(paths.EpochPath, "WoW_tweaked.exe")
return utils.PathExists(testPath)
}
// GetWoWTweakedExecutablePath returns the path to the WoW_tweaked.exe file if it exists
func GetWoWTweakedExecutablePath() string {
if paths.EpochPath == "" {
return ""
}
testPath := filepath.Join(paths.EpochPath, "WoW_tweaked.exe")
if utils.PathExists(testPath) {
return testPath
}
return ""
}
// HandleVanillaTweaksRequest handles the case when vanilla-tweaks is enabled but WoW-tweaked.exe doesn't exist
func HandleVanillaTweaksRequest(myWindow fyne.Window, callback func()) {
dialog.ShowConfirm("Vanilla-tweaks not found",
"WoW-tweaked.exe was not found in your TurtleWoW directory.\n\nWould you like TurtleSilicon to automatically apply vanilla-tweaks for you?",
func(confirmed bool) {
if confirmed {
if err := ApplyVanillaTweaks(myWindow); err != nil {
dialog.ShowError(fmt.Errorf("failed to apply vanilla-tweaks: %v", err), myWindow)
return
}
// After successful patching, execute the callback
callback()
}
}, myWindow)
}

View File

@@ -4,6 +4,7 @@ import (
"bytes" "bytes"
"errors" "errors"
"fmt" "fmt"
"git.burkey.co/eburk/epochcli/pkg/epoch"
"io" "io"
"log" "log"
"os" "os"
@@ -12,20 +13,18 @@ import (
"regexp" "regexp"
"strings" "strings"
"turtlesilicon/pkg/debug" "epochsilicon/pkg/debug"
"turtlesilicon/pkg/paths" // Corrected import path "epochsilicon/pkg/paths" // Corrected import path
"turtlesilicon/pkg/utils" // Corrected import path "epochsilicon/pkg/utils" // Corrected import path
"fyne.io/fyne/v2" "fyne.io/fyne/v2"
"fyne.io/fyne/v2/dialog" "fyne.io/fyne/v2/dialog"
) )
func PatchEpoch(myWindow fyne.Window, updateAllStatuses func()) { func PatchEpoch(myWindow fyne.Window, updateAllStatuses func()) {
// TODO: patch vanilla 3.3.5 to epoch debug.Println("Patch Epoch clicked")
log.Fatal("FIXME")
debug.Println("Patch TurtleWoW clicked")
if paths.EpochPath == "" { if paths.EpochPath == "" {
dialog.ShowError(fmt.Errorf("TurtleWoW path not set. Please set it first."), myWindow) dialog.ShowError(fmt.Errorf("Epoch path not set. Please set it first."), myWindow)
return return
} }
@@ -156,12 +155,6 @@ func PatchEpoch(myWindow fyne.Window, updateAllStatuses func()) {
winerosettaEntry := "winerosetta.dll" winerosettaEntry := "winerosetta.dll"
needsWinerosettaUpdate := true needsWinerosettaUpdate := true
// Check user's preference for libSiliconPatch and shadowLOD
prefs, _ := utils.LoadPrefs()
// Save updated preferences
utils.SavePrefs(prefs)
if fileContentBytes, err := os.ReadFile(dllsTextFile); err == nil { if fileContentBytes, err := os.ReadFile(dllsTextFile); err == nil {
fileContent := string(fileContentBytes) fileContent := string(fileContentBytes)
if strings.Contains(fileContent, winerosettaEntry) { if strings.Contains(fileContent, winerosettaEntry) {
@@ -207,8 +200,18 @@ func PatchEpoch(myWindow fyne.Window, updateAllStatuses func()) {
} }
} }
debug.Println("TurtleWoW patching with bundled resources completed successfully.") debug.Println("Downloading updates from Project Epoch servers.")
dialog.ShowInformation("Success", "TurtleWoW patching process completed using bundled resources.", myWindow) stats, err := epoch.Update(paths.EpochPath, true, true, false)
if err != nil {
errMsg := fmt.Sprintf("failed to update Epoch files: %v", err)
dialog.ShowError(errors.New(errMsg), myWindow)
log.Println(errMsg)
}
log.Printf("Successfully updated %d Epoch files", stats.Updated)
debug.Println("Epoch patching with bundled resources completed successfully.")
dialog.ShowInformation("Success", "Epoch patching process completed.", myWindow)
updateAllStatuses() updateAllStatuses()
} }
@@ -234,7 +237,7 @@ func PatchCrossOver(myWindow fyne.Window, updateAllStatuses func()) {
if err := utils.CopyFile(wineloaderOrig, wineloaderCopy); err != nil { if err := utils.CopyFile(wineloaderOrig, wineloaderCopy); err != nil {
errMsg := fmt.Sprintf("failed to copy wineloader: %v", err) errMsg := fmt.Sprintf("failed to copy wineloader: %v", err)
if strings.Contains(err.Error(), "operation not permitted") { if strings.Contains(err.Error(), "operation not permitted") {
errMsg += "\n\nSolution: Open System Settings, go to Privacy & Security > App Management, and enable TurtleSilicon." errMsg += "\n\nSolution: Open System Settings, go to Privacy & Security > App Management, and enable EpochSilicon."
} }
dialog.ShowError(fmt.Errorf(errMsg), myWindow) dialog.ShowError(fmt.Errorf(errMsg), myWindow)
paths.PatchesAppliedCrossOver = false paths.PatchesAppliedCrossOver = false
@@ -275,18 +278,15 @@ func PatchCrossOver(myWindow fyne.Window, updateAllStatuses func()) {
} }
func UnpatchEpoch(myWindow fyne.Window, updateAllStatuses func()) { func UnpatchEpoch(myWindow fyne.Window, updateAllStatuses func()) {
// TODO: unpatch epoch debug.Println("Unpatch Epoch clicked")
log.Fatal("fixme")
debug.Println("Unpatch TurtleWoW clicked")
if paths.EpochPath == "" { if paths.EpochPath == "" {
dialog.ShowError(fmt.Errorf("TurtleWoW path not set. Please set it first."), myWindow) dialog.ShowError(fmt.Errorf("Epoch path not set. Please set it first."), myWindow)
return return
} }
// Files to remove // Files to remove
winerosettaDllPath := filepath.Join(paths.EpochPath, "winerosetta.dll") winerosettaDllPath := filepath.Join(paths.EpochPath, "winerosetta.dll")
d3d9DllPath := filepath.Join(paths.EpochPath, "d3d9.dll") d3d9DllPath := filepath.Join(paths.EpochPath, "d3d9.dll")
libSiliconPatchDllPath := filepath.Join(paths.EpochPath, "libSiliconPatch.dll")
rosettaX87DirPath := filepath.Join(paths.EpochPath, "rosettax87") rosettaX87DirPath := filepath.Join(paths.EpochPath, "rosettax87")
dllsTextFile := filepath.Join(paths.EpochPath, "dlls.txt") dllsTextFile := filepath.Join(paths.EpochPath, "dlls.txt")
@@ -303,7 +303,7 @@ func UnpatchEpoch(myWindow fyne.Window, updateAllStatuses func()) {
} }
// Remove DLL files // Remove DLL files
filesToRemove := []string{winerosettaDllPath, d3d9DllPath, libSiliconPatchDllPath} filesToRemove := []string{winerosettaDllPath, d3d9DllPath}
for _, file := range filesToRemove { for _, file := range filesToRemove {
if utils.PathExists(file) { if utils.PathExists(file) {
debug.Printf("Removing file: %s", file) debug.Printf("Removing file: %s", file)
@@ -317,7 +317,7 @@ func UnpatchEpoch(myWindow fyne.Window, updateAllStatuses func()) {
} }
} }
// Update dlls.txt file - remove winerosetta.dll and libSiliconPatch.dll entries // Update dlls.txt file - remove winerosetta.dll
if utils.PathExists(dllsTextFile) { if utils.PathExists(dllsTextFile) {
debug.Printf("Updating dlls.txt file: %s", dllsTextFile) debug.Printf("Updating dlls.txt file: %s", dllsTextFile)
content, err := os.ReadFile(dllsTextFile) content, err := os.ReadFile(dllsTextFile)
@@ -331,7 +331,7 @@ func UnpatchEpoch(myWindow fyne.Window, updateAllStatuses func()) {
for _, line := range lines { for _, line := range lines {
trimmedLine := strings.TrimSpace(line) trimmedLine := strings.TrimSpace(line)
if trimmedLine != "winerosetta.dll" && trimmedLine != "libSiliconPatch.dll" { if trimmedLine != "winerosetta.dll" {
filteredLines = append(filteredLines, line) filteredLines = append(filteredLines, line)
} }
} }
@@ -347,9 +347,9 @@ func UnpatchEpoch(myWindow fyne.Window, updateAllStatuses func()) {
} }
} }
debug.Println("TurtleWoW unpatching completed successfully.") debug.Println("Epoch unpatching completed successfully.")
paths.PatchesAppliedEpoch = false paths.PatchesAppliedEpoch = false
dialog.ShowInformation("Success", "TurtleWoW unpatching process completed.", myWindow) dialog.ShowInformation("Success", "Epoch unpatching process completed.", myWindow)
updateAllStatuses() updateAllStatuses()
} }

View File

@@ -6,7 +6,7 @@ import (
"os" "os"
"path/filepath" "path/filepath"
"turtlesilicon/pkg/utils" "epochsilicon/pkg/utils"
"fyne.io/fyne/v2" "fyne.io/fyne/v2"
"fyne.io/fyne/v2/dialog" "fyne.io/fyne/v2/dialog"
@@ -53,14 +53,14 @@ func SelectCrossOverPath(myWindow fyne.Window, crossoverPathLabel *widget.RichTe
}, myWindow) }, myWindow)
} }
func SelectTurtleWoWPath(myWindow fyne.Window, turtlewowPathLabel *widget.RichText, updateAllStatuses func()) { func SelectEpochPath(myWindow fyne.Window, epochPathLabel *widget.RichText, updateAllStatuses func()) {
dialog.ShowFolderOpen(func(uri fyne.ListableURI, err error) { dialog.ShowFolderOpen(func(uri fyne.ListableURI, err error) {
if err != nil { if err != nil {
dialog.ShowError(err, myWindow) dialog.ShowError(err, myWindow)
return return
} }
if uri == nil { if uri == nil {
log.Println("TurtleWoW path selection cancelled.") log.Println("Epoch path selection cancelled.")
updateAllStatuses() updateAllStatuses()
return return
} }
@@ -68,20 +68,20 @@ func SelectTurtleWoWPath(myWindow fyne.Window, turtlewowPathLabel *widget.RichTe
if utils.DirExists(selectedPath) { if utils.DirExists(selectedPath) {
EpochPath = selectedPath EpochPath = selectedPath
PatchesAppliedEpoch = false PatchesAppliedEpoch = false
log.Println("TurtleWoW path set to:", EpochPath) log.Println("Epoch path set to:", EpochPath)
// Save to prefs // Save to prefs
prefs, _ := utils.LoadPrefs() prefs, _ := utils.LoadPrefs()
prefs.EpochPath = selectedPath prefs.EpochPath = selectedPath
utils.SavePrefs(prefs) utils.SavePrefs(prefs)
} else { } else {
dialog.ShowError(fmt.Errorf("invalid selection: '%s' is not a valid directory", selectedPath), myWindow) dialog.ShowError(fmt.Errorf("invalid selection: '%s' is not a valid directory", selectedPath), myWindow)
log.Println("Invalid TurtleWoW path selected:", selectedPath) log.Println("Invalid Epoch path selected:", selectedPath)
} }
updateAllStatuses() updateAllStatuses()
}, myWindow) }, myWindow)
} }
func UpdatePathLabels(crossoverPathLabel, turtlewowPathLabel *widget.RichText) { func UpdatePathLabels(crossoverPathLabel, EpochPathLabel *widget.RichText) {
if CrossoverPath == "" { if CrossoverPath == "" {
crossoverPathLabel.Segments = []widget.RichTextSegment{&widget.TextSegment{Text: "Not set", Style: widget.RichTextStyle{ColorName: theme.ColorNameError}}} crossoverPathLabel.Segments = []widget.RichTextSegment{&widget.TextSegment{Text: "Not set", Style: widget.RichTextStyle{ColorName: theme.ColorNameError}}}
} else { } else {
@@ -90,11 +90,11 @@ func UpdatePathLabels(crossoverPathLabel, turtlewowPathLabel *widget.RichText) {
crossoverPathLabel.Refresh() crossoverPathLabel.Refresh()
if EpochPath == "" { if EpochPath == "" {
turtlewowPathLabel.Segments = []widget.RichTextSegment{&widget.TextSegment{Text: "Not set", Style: widget.RichTextStyle{ColorName: theme.ColorNameError}}} EpochPathLabel.Segments = []widget.RichTextSegment{&widget.TextSegment{Text: "Not set", Style: widget.RichTextStyle{ColorName: theme.ColorNameError}}}
} else { } else {
turtlewowPathLabel.Segments = []widget.RichTextSegment{&widget.TextSegment{Text: EpochPath, Style: widget.RichTextStyle{ColorName: theme.ColorNameSuccess}}} EpochPathLabel.Segments = []widget.RichTextSegment{&widget.TextSegment{Text: EpochPath, Style: widget.RichTextStyle{ColorName: theme.ColorNameSuccess}}}
} }
turtlewowPathLabel.Refresh() EpochPathLabel.Refresh()
} }
func CheckDefaultCrossOverPath() { func CheckDefaultCrossOverPath() {

View File

@@ -10,8 +10,8 @@ import (
"syscall" "syscall"
"time" "time"
"turtlesilicon/pkg/paths" "epochsilicon/pkg/paths"
"turtlesilicon/pkg/utils" "epochsilicon/pkg/utils"
"fyne.io/fyne/v2" "fyne.io/fyne/v2"
"fyne.io/fyne/v2/container" "fyne.io/fyne/v2/container"
@@ -80,7 +80,7 @@ func StartRosettaX87Service(myWindow fyne.Window, updateAllStatuses func()) {
log.Println("Starting RosettaX87 service...") log.Println("Starting RosettaX87 service...")
if paths.EpochPath == "" { if paths.EpochPath == "" {
dialog.ShowError(fmt.Errorf("TurtleWoW path not set. Please set it first"), myWindow) dialog.ShowError(fmt.Errorf("Epoch path not set. Please set it first"), myWindow)
return return
} }
@@ -88,7 +88,7 @@ func StartRosettaX87Service(myWindow fyne.Window, updateAllStatuses func()) {
rosettaX87Exe := filepath.Join(rosettaX87Dir, "rosettax87") rosettaX87Exe := filepath.Join(rosettaX87Dir, "rosettax87")
if !utils.PathExists(rosettaX87Exe) { if !utils.PathExists(rosettaX87Exe) {
dialog.ShowError(fmt.Errorf("rosettax87 executable not found at %s. Please apply TurtleWoW patches first", rosettaX87Exe), myWindow) dialog.ShowError(fmt.Errorf("rosettax87 executable not found at %s. Please apply Epoch patches first", rosettaX87Exe), myWindow)
return return
} }

View File

@@ -5,11 +5,11 @@ import (
"strings" "strings"
"time" "time"
"turtlesilicon/pkg/debug" "epochsilicon/pkg/debug"
"turtlesilicon/pkg/launcher" "epochsilicon/pkg/launcher"
"turtlesilicon/pkg/patching" "epochsilicon/pkg/patching"
"turtlesilicon/pkg/service" "epochsilicon/pkg/service"
"turtlesilicon/pkg/utils" "epochsilicon/pkg/utils"
"fyne.io/fyne/v2" "fyne.io/fyne/v2"
"fyne.io/fyne/v2/container" "fyne.io/fyne/v2/container"
@@ -75,10 +75,10 @@ func createOptionsComponents() {
// createPatchingButtons creates all patching-related buttons // createPatchingButtons creates all patching-related buttons
func createPatchingButtons(myWindow fyne.Window) { func createPatchingButtons(myWindow fyne.Window) {
patchTurtleWoWButton = widget.NewButton("Patch Epoch", func() { patchEpochButton = widget.NewButton("Patch Epoch", func() {
patching.PatchEpoch(myWindow, UpdateAllStatuses) patching.PatchEpoch(myWindow, UpdateAllStatuses)
}) })
unpatchTurtleWoWButton = widget.NewButton("Unpatch Epoch", func() { unpatchEpochButton = widget.NewButton("Unpatch Epoch", func() {
patching.UnpatchEpoch(myWindow, UpdateAllStatuses) patching.UnpatchEpoch(myWindow, UpdateAllStatuses)
}) })
patchCrossOverButton = widget.NewButton("Patch CrossOver", func() { patchCrossOverButton = widget.NewButton("Patch CrossOver", func() {
@@ -123,7 +123,7 @@ func createBottomBar(myWindow fyne.Window) fyne.CanvasObject {
// GitHub button // GitHub button
githubButton := widget.NewButton("GitHub", func() { githubButton := widget.NewButton("GitHub", func() {
githubURL := "https://github.com/tairasu/TurtleSilicon" githubURL := "https://github.com/tairasu/EpochSilicon"
parsedURL, err := url.Parse(githubURL) parsedURL, err := url.Parse(githubURL)
if err != nil { if err != nil {
debug.Printf("Error parsing GitHub URL: %v", err) debug.Printf("Error parsing GitHub URL: %v", err)

View File

@@ -1,8 +1,8 @@
package ui package ui
import ( import (
"turtlesilicon/pkg/debug" "epochsilicon/pkg/debug"
"turtlesilicon/pkg/paths" "epochsilicon/pkg/paths"
"fyne.io/fyne/v2" "fyne.io/fyne/v2"
"fyne.io/fyne/v2/canvas" "fyne.io/fyne/v2/canvas"
@@ -13,11 +13,11 @@ import (
// createHeaderContainer creates the header with title and subtitle // createHeaderContainer creates the header with title and subtitle
func createHeaderContainer() fyne.CanvasObject { func createHeaderContainer() fyne.CanvasObject {
// Main title // Main title
titleText := widget.NewRichTextFromMarkdown("# TurtleSilicon") titleText := widget.NewRichTextFromMarkdown("# EpochSilicon")
titleText.Wrapping = fyne.TextWrapOff titleText.Wrapping = fyne.TextWrapOff
// Subtitle // Subtitle
subtitleText := widget.NewLabel("A TurtleWoW launcher for Apple Silicon Macs") subtitleText := widget.NewLabel("An Epoch launcher for Apple Silicon Macs")
subtitleText.Alignment = fyne.TextAlignCenter subtitleText.Alignment = fyne.TextAlignCenter
// Create header container // Create header container
@@ -57,14 +57,14 @@ func createLogoContainer() fyne.CanvasObject {
return logoContainer return logoContainer
} }
// createPathSelectionForm creates the form for selecting CrossOver and TurtleWoW paths // createPathSelectionForm creates the form for selecting CrossOver and Epoch paths
func createPathSelectionForm(myWindow fyne.Window) *widget.Form { func createPathSelectionForm(myWindow fyne.Window) *widget.Form {
pathSelectionForm := widget.NewForm( pathSelectionForm := widget.NewForm(
widget.NewFormItem("CrossOver Path:", container.NewBorder(nil, nil, nil, widget.NewButton("Set/Change", func() { widget.NewFormItem("CrossOver Path:", container.NewBorder(nil, nil, nil, widget.NewButton("Set/Change", func() {
paths.SelectCrossOverPath(myWindow, crossoverPathLabel, UpdateAllStatuses) paths.SelectCrossOverPath(myWindow, crossoverPathLabel, UpdateAllStatuses)
}), crossoverPathLabel)), }), crossoverPathLabel)),
widget.NewFormItem("TurtleWoW Path:", container.NewBorder(nil, nil, nil, widget.NewButton("Set/Change", func() { widget.NewFormItem("Epoch Path:", container.NewBorder(nil, nil, nil, widget.NewButton("Set/Change", func() {
paths.SelectTurtleWoWPath(myWindow, epochPathLabel, UpdateAllStatuses) paths.SelectEpochPath(myWindow, epochPathLabel, UpdateAllStatuses)
}), epochPathLabel)), }), epochPathLabel)),
) )
@@ -76,7 +76,7 @@ func createPatchOperationsLayout() fyne.CanvasObject {
patchOperationsLayout := container.NewVBox( patchOperationsLayout := container.NewVBox(
widget.NewSeparator(), widget.NewSeparator(),
container.NewGridWithColumns(4, container.NewGridWithColumns(4,
widget.NewLabel("TurtleWoW Patch:"), epochStatusLabel, patchTurtleWoWButton, unpatchTurtleWoWButton, widget.NewLabel("Epoch Patch:"), epochStatusLabel, patchEpochButton, unpatchEpochButton,
), ),
container.NewGridWithColumns(4, container.NewGridWithColumns(4,
widget.NewLabel("CrossOver Patch:"), crossoverStatusLabel, patchCrossOverButton, unpatchCrossOverButton, widget.NewLabel("CrossOver Patch:"), crossoverStatusLabel, patchCrossOverButton, unpatchCrossOverButton,

View File

@@ -13,8 +13,8 @@ import (
"howett.net/plist" "howett.net/plist"
"turtlesilicon/pkg/paths" "epochsilicon/pkg/paths"
"turtlesilicon/pkg/utils" "epochsilicon/pkg/utils"
) )
// showOptionsPopup creates and shows an integrated popup window for options // showOptionsPopup creates and shows an integrated popup window for options
@@ -32,7 +32,6 @@ func showOptionsPopup() {
widget.NewSeparator(), widget.NewSeparator(),
metalHudCheckbox, metalHudCheckbox,
showTerminalCheckbox, showTerminalCheckbox,
vanillaTweaksCheckbox,
autoDeleteWdbCheckbox, autoDeleteWdbCheckbox,
widget.NewSeparator(), widget.NewSeparator(),
container.NewBorder(nil, nil, nil, container.NewHBox(enableOptionAsAltButton, disableOptionAsAltButton), optionAsAltStatusLabel), container.NewBorder(nil, nil, nil, container.NewHBox(enableOptionAsAltButton, disableOptionAsAltButton), optionAsAltStatusLabel),
@@ -203,8 +202,8 @@ func showTroubleshootingPopup() {
rowCrossover := container.NewBorder(nil, nil, widget.NewLabel("CrossOver version:"), crossoverStatusShort, nil) rowCrossover := container.NewBorder(nil, nil, widget.NewLabel("CrossOver version:"), crossoverStatusShort, nil)
rowWDB := container.NewBorder(nil, nil, widget.NewLabel("Delete WDB directory (cache):"), wdbDeleteButton, nil) rowWDB := container.NewBorder(nil, nil, widget.NewLabel("Delete WDB directory (cache):"), wdbDeleteButton, nil)
rowWine := container.NewBorder(nil, nil, widget.NewLabel("Delete Wine prefixes (~/.wine & TurtleWoW/.wine):"), wineDeleteButton, nil) rowWine := container.NewBorder(nil, nil, widget.NewLabel("Delete Wine prefixes (~/.wine & Epoch/.wine):"), wineDeleteButton, nil)
appMgmtNote := widget.NewLabel("Please ensure TurtleSilicon is enabled in System Settings > Privacy & Security > App Management.") appMgmtNote := widget.NewLabel("Please ensure EpochSilicon is enabled in System Settings > Privacy & Security > App Management.")
appMgmtNote.Wrapping = fyne.TextWrapWord appMgmtNote.Wrapping = fyne.TextWrapWord
appMgmtNote.TextStyle = fyne.TextStyle{Italic: true} appMgmtNote.TextStyle = fyne.TextStyle{Italic: true}

View File

@@ -1,14 +1,16 @@
package ui package ui
import ( import (
"epochsilicon/pkg/debug"
"git.burkey.co/eburk/epochcli/pkg/epoch"
"os" "os"
"path/filepath" "path/filepath"
"strings" "strings"
"time" "time"
"turtlesilicon/pkg/paths" "epochsilicon/pkg/paths"
"turtlesilicon/pkg/service" "epochsilicon/pkg/service"
"turtlesilicon/pkg/utils" "epochsilicon/pkg/utils"
"fyne.io/fyne/v2" "fyne.io/fyne/v2"
"fyne.io/fyne/v2/theme" "fyne.io/fyne/v2/theme"
@@ -75,7 +77,7 @@ func updateCrossoverStatus() {
crossoverStatusLabel.Refresh() crossoverStatusLabel.Refresh()
} }
// updateEpochStatus updates TurtleWoW path and patch status // updateEpochStatus updates Epoch path and patch status
func updateEpochStatus() { func updateEpochStatus() {
if paths.EpochPath == "" { if paths.EpochPath == "" {
epochPathLabel.Segments = []widget.RichTextSegment{&widget.TextSegment{Text: "Not set", Style: widget.RichTextStyle{ColorName: theme.ColorNameError}}} epochPathLabel.Segments = []widget.RichTextSegment{&widget.TextSegment{Text: "Not set", Style: widget.RichTextStyle{ColorName: theme.ColorNameError}}}
@@ -86,7 +88,6 @@ func updateEpochStatus() {
// Check if all required files exist // Check if all required files exist
winerosettaDllPath := filepath.Join(paths.EpochPath, "winerosetta.dll") winerosettaDllPath := filepath.Join(paths.EpochPath, "winerosetta.dll")
d3d9DllPath := filepath.Join(paths.EpochPath, "d3d9.dll") d3d9DllPath := filepath.Join(paths.EpochPath, "d3d9.dll")
libSiliconPatchDllPath := filepath.Join(paths.EpochPath, "libSiliconPatch.dll")
rosettaX87DirPath := filepath.Join(paths.EpochPath, "rosettax87") rosettaX87DirPath := filepath.Join(paths.EpochPath, "rosettax87")
dllsTextFile := filepath.Join(paths.EpochPath, "dlls.txt") dllsTextFile := filepath.Join(paths.EpochPath, "dlls.txt")
rosettaX87ExePath := filepath.Join(rosettaX87DirPath, "rosettax87") rosettaX87ExePath := filepath.Join(rosettaX87DirPath, "rosettax87")
@@ -98,7 +99,7 @@ func updateEpochStatus() {
contentStr := string(fileContent) contentStr := string(fileContent)
winerosettaPresent := strings.Contains(contentStr, "winerosetta.dll") winerosettaPresent := strings.Contains(contentStr, "winerosetta.dll")
// Validate dlls.txt: winerosetta must be present, libSiliconPatch based on setting // Validate dlls.txt: winerosetta must be present
if winerosettaPresent { if winerosettaPresent {
dllsFileValid = true dllsFileValid = true
} }
@@ -111,35 +112,46 @@ func updateEpochStatus() {
rosettaX87CorrectSize := utils.CompareFileWithBundledResource(rosettaX87ExePath, "rosettax87/rosettax87") rosettaX87CorrectSize := utils.CompareFileWithBundledResource(rosettaX87ExePath, "rosettax87/rosettax87")
libRuntimeRosettaX87CorrectSize := utils.CompareFileWithBundledResource(libRuntimeRosettaX87Path, "rosettax87/libRuntimeRosettax87") libRuntimeRosettaX87CorrectSize := utils.CompareFileWithBundledResource(libRuntimeRosettaX87Path, "rosettax87/libRuntimeRosettax87")
if utils.PathExists(winerosettaDllPath) && utils.PathExists(d3d9DllPath) && utils.PathExists(libSiliconPatchDllPath) && if utils.PathExists(winerosettaDllPath) && utils.PathExists(d3d9DllPath) &&
utils.DirExists(rosettaX87DirPath) && utils.PathExists(rosettaX87ExePath) && utils.DirExists(rosettaX87DirPath) && utils.PathExists(rosettaX87ExePath) &&
utils.PathExists(libRuntimeRosettaX87Path) && dllsFileValid && utils.PathExists(libRuntimeRosettaX87Path) && dllsFileValid &&
winerosettaDllCorrectSize && d3d9DllCorrectSize && winerosettaDllCorrectSize && d3d9DllCorrectSize &&
rosettaX87CorrectSize && libRuntimeRosettaX87CorrectSize { rosettaX87CorrectSize && libRuntimeRosettaX87CorrectSize {
paths.PatchesAppliedEpoch = true paths.PatchesAppliedEpoch = true
} }
// Check for Epoch-specific files, set PatchesAppliedEpoch to false if not updated
stats, err := epoch.Update(paths.EpochPath, false, true, true)
if err != nil {
paths.PatchesAppliedEpoch = false
debug.Printf("Failed to get download Epoch patches: %v", err)
}
if stats.Outdated > 0 {
paths.PatchesAppliedEpoch = false
}
} }
epochPathLabel.Refresh() epochPathLabel.Refresh()
if paths.PatchesAppliedEpoch { if paths.PatchesAppliedEpoch {
epochStatusLabel.Segments = []widget.RichTextSegment{&widget.TextSegment{Text: "Patched", Style: widget.RichTextStyle{ColorName: theme.ColorNameSuccess}}} epochStatusLabel.Segments = []widget.RichTextSegment{&widget.TextSegment{Text: "Patched", Style: widget.RichTextStyle{ColorName: theme.ColorNameSuccess}}}
if patchTurtleWoWButton != nil { if patchEpochButton != nil {
patchTurtleWoWButton.Disable() patchEpochButton.Disable()
} }
if unpatchTurtleWoWButton != nil { if unpatchEpochButton != nil {
unpatchTurtleWoWButton.Enable() unpatchEpochButton.Enable()
} }
} else { } else {
epochStatusLabel.Segments = []widget.RichTextSegment{&widget.TextSegment{Text: "Not patched", Style: widget.RichTextStyle{ColorName: theme.ColorNameError}}} epochStatusLabel.Segments = []widget.RichTextSegment{&widget.TextSegment{Text: "Not patched", Style: widget.RichTextStyle{ColorName: theme.ColorNameError}}}
if patchTurtleWoWButton != nil { if patchEpochButton != nil {
if paths.EpochPath != "" { if paths.EpochPath != "" {
patchTurtleWoWButton.Enable() patchEpochButton.Enable()
} else { } else {
patchTurtleWoWButton.Disable() patchEpochButton.Disable()
} }
} }
if unpatchTurtleWoWButton != nil { if unpatchEpochButton != nil {
unpatchTurtleWoWButton.Disable() unpatchEpochButton.Disable()
} }
} }
epochStatusLabel.Refresh() epochStatusLabel.Refresh()

View File

@@ -1,8 +1,8 @@
package ui package ui
import ( import (
"turtlesilicon/pkg/paths" "epochsilicon/pkg/paths"
"turtlesilicon/pkg/utils" "epochsilicon/pkg/utils"
"fyne.io/fyne/v2" "fyne.io/fyne/v2"
"fyne.io/fyne/v2/container" "fyne.io/fyne/v2/container"

View File

@@ -5,8 +5,8 @@ import (
"strings" "strings"
"time" "time"
"turtlesilicon/pkg/debug" "epochsilicon/pkg/debug"
"turtlesilicon/pkg/utils" "epochsilicon/pkg/utils"
"fyne.io/fyne/v2" "fyne.io/fyne/v2"
"fyne.io/fyne/v2/container" "fyne.io/fyne/v2/container"

View File

@@ -20,9 +20,9 @@ var (
launchButton *widget.Button launchButton *widget.Button
playButton *widget.Button playButton *widget.Button
playButtonText *widget.RichText playButtonText *widget.RichText
patchTurtleWoWButton *widget.Button patchEpochButton *widget.Button
patchCrossOverButton *widget.Button patchCrossOverButton *widget.Button
unpatchTurtleWoWButton *widget.Button unpatchEpochButton *widget.Button
unpatchCrossOverButton *widget.Button unpatchCrossOverButton *widget.Button
startServiceButton *widget.Button startServiceButton *widget.Button
stopServiceButton *widget.Button stopServiceButton *widget.Button
@@ -30,7 +30,6 @@ var (
// Option checkboxes // Option checkboxes
metalHudCheckbox *widget.Check metalHudCheckbox *widget.Check
showTerminalCheckbox *widget.Check showTerminalCheckbox *widget.Check
vanillaTweaksCheckbox *widget.Check
autoDeleteWdbCheckbox *widget.Check autoDeleteWdbCheckbox *widget.Check
// Recommended settings button // Recommended settings button
@@ -45,19 +44,6 @@ var (
// Environment variables entry // Environment variables entry
envVarsEntry *widget.Entry envVarsEntry *widget.Entry
// Graphics settings checkboxes
reduceTerrainDistanceCheckbox *widget.Check
setMultisampleTo2xCheckbox *widget.Check
setShadowLOD0Checkbox *widget.Check
libSiliconPatchCheckbox *widget.Check
applyGraphicsSettingsButton *widget.Button
// Graphics settings help buttons
reduceTerrainDistanceHelpButton *widget.Button
setMultisampleTo2xHelpButton *widget.Button
setShadowLOD0HelpButton *widget.Button
libSiliconPatchHelpButton *widget.Button
// Window reference for popup functionality // Window reference for popup functionality
currentWindow fyne.Window currentWindow fyne.Window

View File

@@ -8,7 +8,7 @@ import (
) )
const ( const (
serviceName = "TurtleSilicon" serviceName = "EpochSilicon"
accountName = "sudo_password" accountName = "sudo_password"
) )

View File

@@ -23,7 +23,7 @@ func getPrefsPath() (string, error) {
if err != nil { if err != nil {
return "", err return "", err
} }
return filepath.Join(dir, "TurtleSilicon", "prefs.json"), nil return filepath.Join(dir, "EpochSilicon", "prefs.json"), nil
} }
func LoadPrefs() (*UserPrefs, error) { func LoadPrefs() (*UserPrefs, error) {

View File

@@ -11,7 +11,7 @@ import (
"path/filepath" "path/filepath"
"strings" "strings"
"turtlesilicon/pkg/debug" "epochsilicon/pkg/debug"
"fyne.io/fyne/v2" "fyne.io/fyne/v2"
"fyne.io/fyne/v2/dialog" "fyne.io/fyne/v2/dialog"
@@ -130,7 +130,7 @@ func QuotePathForShell(path string) string {
} }
func CheckForUpdate(currentVersion string) (latestVersion, releaseNotes string, updateAvailable bool, err error) { func CheckForUpdate(currentVersion string) (latestVersion, releaseNotes string, updateAvailable bool, err error) {
resp, err := http.Get("https://api.github.com/repos/tairasu/TurtleSilicon/releases/latest") resp, err := http.Get("https://api.github.com/repos/tairasu/EpochSilicon/releases/latest")
if err != nil { if err != nil {
return "", "", false, err return "", "", false, err
} }
@@ -163,7 +163,7 @@ type Asset struct {
// CheckForUpdateWithAssets returns update information including download assets // CheckForUpdateWithAssets returns update information including download assets
func CheckForUpdateWithAssets(currentVersion string) (*UpdateInfo, bool, error) { func CheckForUpdateWithAssets(currentVersion string) (*UpdateInfo, bool, error) {
resp, err := http.Get("https://api.github.com/repos/tairasu/TurtleSilicon/releases/latest") resp, err := http.Get("https://api.github.com/repos/tairasu/EpochSilicon/releases/latest")
if err != nil { if err != nil {
return nil, false, err return nil, false, err
} }
@@ -201,7 +201,7 @@ func CheckForUpdateWithAssets(currentVersion string) (*UpdateInfo, bool, error)
// DownloadUpdate downloads the latest release and returns the path to the downloaded file // DownloadUpdate downloads the latest release and returns the path to the downloaded file
func DownloadUpdate(downloadURL string, progressCallback func(downloaded, total int64)) (string, error) { func DownloadUpdate(downloadURL string, progressCallback func(downloaded, total int64)) (string, error) {
// Create temporary file // Create temporary file
tempFile, err := os.CreateTemp("", "TurtleSilicon-update-*.dmg") tempFile, err := os.CreateTemp("", "EpochSilicon-update-*.dmg")
if err != nil { if err != nil {
return "", fmt.Errorf("failed to create temp file: %v", err) return "", fmt.Errorf("failed to create temp file: %v", err)
} }
@@ -349,12 +349,12 @@ func InstallUpdate(dmgPath string) error {
var newAppPath string var newAppPath string
// First, try the exact name // First, try the exact name
exactPath := filepath.Join(mountPoint, "TurtleSilicon.app") exactPath := filepath.Join(mountPoint, "EpochSilicon.app")
if PathExists(exactPath) { if PathExists(exactPath) {
newAppPath = exactPath newAppPath = exactPath
} else { } else {
// Search for any .app bundle in the mount point // Search for any .app bundle in the mount point
debug.Printf("TurtleSilicon.app not found at exact path, searching for .app bundles") debug.Printf("EpochSilicon.app not found at exact path, searching for .app bundles")
entries, err := os.ReadDir(mountPoint) entries, err := os.ReadDir(mountPoint)
if err != nil { if err != nil {
return fmt.Errorf("failed to read DMG contents: %v", err) return fmt.Errorf("failed to read DMG contents: %v", err)
@@ -406,7 +406,7 @@ func InstallUpdate(dmgPath string) error {
} }
// Fix executable permissions for the main binary // Fix executable permissions for the main binary
executablePath := filepath.Join(currentAppPath, "Contents", "MacOS", "turtlesilicon") executablePath := filepath.Join(currentAppPath, "Contents", "MacOS", "epochsilicon")
if PathExists(executablePath) { if PathExists(executablePath) {
debug.Printf("Setting executable permissions for: %s", executablePath) debug.Printf("Setting executable permissions for: %s", executablePath)
if err := os.Chmod(executablePath, 0755); err != nil { if err := os.Chmod(executablePath, 0755); err != nil {
@@ -466,7 +466,7 @@ func TestDMGMount(dmgPath string) (string, string, error) {
if infoErr == nil { if infoErr == nil {
infoLines := strings.Split(string(infoOutput), "\n") infoLines := strings.Split(string(infoOutput), "\n")
for _, line := range infoLines { for _, line := range infoLines {
if strings.Contains(line, "/Volumes/") && strings.Contains(line, "TurtleSilicon") { if strings.Contains(line, "/Volumes/") && strings.Contains(line, "EpochSilicon") {
line = strings.TrimSpace(line) line = strings.TrimSpace(line)
if strings.HasPrefix(line, "/Volumes/") { if strings.HasPrefix(line, "/Volumes/") {
mountPoint = line mountPoint = line
@@ -487,12 +487,12 @@ func TestDMGMount(dmgPath string) (string, string, error) {
var newAppPath string var newAppPath string
// First, try the exact name // First, try the exact name
exactPath := filepath.Join(mountPoint, "TurtleSilicon.app") exactPath := filepath.Join(mountPoint, "EpochSilicon.app")
if PathExists(exactPath) { if PathExists(exactPath) {
newAppPath = exactPath newAppPath = exactPath
} else { } else {
// Search for any .app bundle in the mount point // Search for any .app bundle in the mount point
debug.Printf("TurtleSilicon.app not found at exact path, searching for .app bundles") debug.Printf("EpochSilicon.app not found at exact path, searching for .app bundles")
entries, err := os.ReadDir(mountPoint) entries, err := os.ReadDir(mountPoint)
if err != nil { if err != nil {
// Unmount before returning error // Unmount before returning error