first epoch pass
Some checks failed
Build Go/Fyne App for macOS ARM64 / build (pull_request) Has been cancelled
Some checks failed
Build Go/Fyne App for macOS ARM64 / build (pull_request) Has been cancelled
This commit is contained in:
8
.github/workflows/build.yml
vendored
8
.github/workflows/build.yml
vendored
@@ -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
6
.gitignore
vendored
@@ -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
|
@@ -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>
|
||||||
|
Binary file not shown.
@@ -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
BIN
Icon.png
Binary file not shown.
Before Width: | Height: | Size: 313 KiB After Width: | Height: | Size: 14 KiB |
40
Makefile
40
Makefile
@@ -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
|
@@ -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
41
go.mod
@@ -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
38
go.sum
@@ -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=
|
||||||
|
6
main.go
6
main.go
@@ -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"
|
||||||
|
@@ -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
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -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")
|
||||||
|
@@ -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)
|
|
||||||
}
|
|
@@ -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()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -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() {
|
||||||
|
@@ -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
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -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)
|
||||||
|
@@ -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,
|
||||||
|
@@ -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}
|
||||||
|
|
||||||
|
@@ -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()
|
||||||
|
@@ -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"
|
||||||
|
@@ -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"
|
||||||
|
@@ -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
|
||||||
|
|
||||||
|
@@ -8,7 +8,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
serviceName = "TurtleSilicon"
|
serviceName = "EpochSilicon"
|
||||||
accountName = "sudo_password"
|
accountName = "sudo_password"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@@ -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) {
|
||||||
|
@@ -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
|
||||||
|
Reference in New Issue
Block a user