diff --git a/Makefile b/Makefile index 8f8cd56..3313372 100644 --- a/Makefile +++ b/Makefile @@ -1,7 +1,7 @@ all: build-windows build-linux build-windows: - env GOOS=windows GOARCH=amd64 go build -o ./build/eu4-checksum-patcher-windows.exe *.go + env GOOS=windows GOARCH=amd64 go build -o ./build/universal-checksum-patcher-windows.exe *.go build-linux: - env GOOS=linux GOARCH=amd64 go build -o ./build/eu4-checksum-patcher-linux *.go \ No newline at end of file + env GOOS=linux GOARCH=amd64 go build -o ./build/universal-checksum-patcher-linux *.go \ No newline at end of file diff --git a/go.mod b/go.mod index c78eacb..21b9fd7 100644 --- a/go.mod +++ b/go.mod @@ -1,3 +1,10 @@ module github.com/goshathebusiness/eu4-checksum-patcher go 1.19 + +require github.com/manifoldco/promptui v0.9.0 + +require ( + github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e // indirect + golang.org/x/sys v0.0.0-20181122145206-62eef0e2fa9b // indirect +) diff --git a/go.sum b/go.sum index e69de29..34fdb2a 100644 --- a/go.sum +++ b/go.sum @@ -0,0 +1,10 @@ +github.com/chzyer/logex v1.1.10 h1:Swpa1K6QvQznwJRcfTfQJmTE72DqScAa40E+fbHEXEE= +github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= +github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e h1:fY5BOSpyZCqRo5OhCuC+XN+r/bBCmeuuJtjz+bCNIf8= +github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= +github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1 h1:q763qf9huN11kDQavWsoZXJNW3xEE4JJyHa5Q25/sd8= +github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= +github.com/manifoldco/promptui v0.9.0 h1:3V4HzJk1TtXW1MTZMP7mdlwbBpIinw3HztaIlYthEiA= +github.com/manifoldco/promptui v0.9.0/go.mod h1:ka04sppxSGFAtxX0qhlYQjISsg9mR4GWtQEhdbn6Pgg= +golang.org/x/sys v0.0.0-20181122145206-62eef0e2fa9b h1:MQE+LT/ABUuuvEZ+YQAMSXindAdUh7slEmAkup74op4= +golang.org/x/sys v0.0.0-20181122145206-62eef0e2fa9b/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= diff --git a/main.go b/main.go index 6a4da96..52c2934 100644 --- a/main.go +++ b/main.go @@ -1,12 +1,40 @@ package main -import "runtime" +import ( + "fmt" + "runtime" + + "github.com/manifoldco/promptui" +) func main() { - originalFileName := "eu4" - finalFileName := "eu4" + prompt := promptui.Select{ + Label: "Select game to patch", + Items: []string{"Europa Universalis IV", "Hearts of Iron IV"}, + } + + _, result, err := prompt.Run() + + if err != nil { + fmt.Printf("Prompt failed %v\n", err) + return + } + + switch result { + case "Europa Universalis IV": + err = applyPatch(false, "eu4", runtime.GOOS) + case "Hearts of Iron IV": + err = applyPatch(false, "hoi4", runtime.GOOS) + } - applyPatch(false, originalFileName, finalFileName, runtime.GOOS) + if err != nil { + fmt.Println("ERROR:", err) + fmt.Println("Patch not installed, no file has been changed") + } else { + fmt.Println("Patch successfully installed, your original executable has been backuped in [original name]_backup") + } + fmt.Println("Press enter to exit") + fmt.Scanln() } diff --git a/patch.go b/patch.go index 4a720f8..488d86e 100644 --- a/patch.go +++ b/patch.go @@ -52,16 +52,48 @@ func compareExes(exeAName, exeBName string) bool { return reflect.DeepEqual(byteA, byteB) } -func applyPatch(test bool, originalFileName, finalFileName, OS string) error { +func applyPatch(test bool, originalFileName, OS string) error { var fileExtension string var hexExists []string var hexWanted []string - hexExistsWindows := []string{"48", "8D", "0D", "??", "??", "??", "01", "E8", "??", "??", "??", "01", "85", "C0", "0F", "94", "C3", "E8", "97", "79", "E9"} - hexWantedWindows := []string{"48", "8D", "0D", "??", "??", "??", "01", "E8", "??", "??", "??", "01", "31", "C0", "0F", "94", "C3", "E8", "97", "79", "E9"} + var hexExistsWindows []string + var hexWantedWindows []string + var hexExistsLinux []string + var hexWantedLinux []string + // EU4 + hexExistsEU4Windows := []string{"48", "8D", "0D", "??", "??", "??", "01", "E8", "??", "??", "??", "01", "85", "C0", "0F", "94", "C3", "E8", "97", "79", "E9"} + hexWantedEU4Windows := []string{"48", "8D", "0D", "??", "??", "??", "01", "E8", "??", "??", "??", "01", "31", "C0", "0F", "94", "C3", "E8", "97", "79", "E9"} + hexExistsEU4Linux := []string{"E8", "65", "95", "E5", "FF", "89", "C3", "E8", "38", "08", "EC", "FF", "31", "F6", "85", "DB", "40", "0F", "94", "C6", "48", "89", "C7"} + hexWantedEU4Linux := []string{"E8", "65", "95", "E5", "FF", "89", "C3", "E8", "38", "08", "EC", "FF", "31", "F6", "31", "DB", "40", "0F", "94", "C6", "48", "89", "C7"} + // HOI4 + hexExistsHOI4Windows := []string{"48", "8D", "0D", "77", "B6", "C9", "01", "E8", "CA", "86", "B3", "01", "85", "C0", "0F", "94", "C3", "E8", "90"} + hexWantedHOI4Windows := []string{"48", "8D", "0D", "77", "B6", "C9", "01", "E8", "CA", "86", "B3", "01", "31", "C0", "0F", "94", "C3", "E8", "90"} + hexExistsHOI4Linux := []string{} + hexWantedHOI4Linux := []string{} + + if strings.Contains(originalFileName, "eu4") { + hexExistsWindows = hexExistsEU4Windows + hexWantedWindows = hexWantedEU4Windows + + hexExistsLinux = hexExistsEU4Linux + hexWantedLinux = hexWantedEU4Linux + } else if strings.Contains(originalFileName, "hoi4") { + if OS == "linux" { + + return errors.New("patching linux version of Hearts of Iron IV is not currently supported") + } + + hexExistsWindows = hexExistsHOI4Windows + hexWantedWindows = hexWantedHOI4Windows + + hexExistsLinux = hexExistsHOI4Linux + hexWantedLinux = hexWantedHOI4Linux + + } else { + return errors.New("not supported executable") + } - hexExistsLinux := []string{"E8", "65", "95", "E5", "FF", "89", "C3", "E8", "38", "08", "EC", "FF", "31", "F6", "85", "DB", "40", "0F", "94", "C6", "48", "89", "C7"} - hexWantedLinux := []string{"E8", "65", "95", "E5", "FF", "89", "C3", "E8", "38", "08", "EC", "FF", "31", "F6", "31", "DB", "40", "0F", "94", "C6", "48", "89", "C7"} switch OS { case "windows": fileExtension = ".exe" @@ -73,15 +105,12 @@ func applyPatch(test bool, originalFileName, finalFileName, OS string) error { hexWanted = hexWantedLinux default: fileExtension = "" - fmt.Printf("ERROR: This OS is not supported") - fmt.Println("Press enter to exit") - fmt.Scanln() - return errors.New("This OS is not supported") + return fmt.Errorf("this OS (%s) is not supported", OS) + } byteExists := make([]byte, len(hexExists)) byteWanted := make([]byte, len(hexWanted)) - for i, h := range hexExists { var value int64 if h == "??" { @@ -106,13 +135,9 @@ func applyPatch(test bool, originalFileName, finalFileName, OS string) error { }() if _, err := os.Stat(originalFileName + fileExtension); errors.Is(err, os.ErrNotExist) { - fmt.Printf("ERROR: Cannot locate %s in current folder\n", originalFileName+fileExtension) - if !test { - fmt.Println("Press enter to exit") - fmt.Scanln() - } - return errors.New("Cant find executable file") + return fmt.Errorf("cannot locate %s in current folder", originalFileName+fileExtension) } + originalByte, err := os.ReadFile(originalFileName + fileExtension) if err != nil { return err @@ -123,13 +148,9 @@ func applyPatch(test bool, originalFileName, finalFileName, OS string) error { matchesNeeded := len(byteExists) matches := 0 status := false - if !test { - fmt.Println("Patching process started") - } for i := 0; i < len(finalByte); i++ { - - if finalByte[i] == byteExists[0] && finalByte[i+len(byteExists)-1] == byteExists[len(byteExists)-1] { + if finalByte[i] == byteExists[0] { matches++ for j := range byteExists { if (finalByte[i+j] == byteExists[j]) || (byteExists[j] == 0) { @@ -140,31 +161,25 @@ func applyPatch(test bool, originalFileName, finalFileName, OS string) error { } } if matches >= matchesNeeded { - if !test { - fmt.Println("Needed byte-combination finded") - } for k := range byteExists { if byteExists[k] != 0 { finalByte[i+k] = byteWanted[k] } } status = true + break } } } if !status { - fmt.Printf("ERROR: Unsupported version of %s or it's patched already. Patch has not been applied\n", originalFileName+fileExtension) + os.Remove(originalFileName + "_backup" + fileExtension) - if !test { - fmt.Println("Press enter to exit") - fmt.Scanln() - } - return errors.New("Cant apply patch") + return fmt.Errorf("unsupported version of %s or it's patched already. Patch has not been applied", originalFileName+fileExtension) } - out, err := os.Create(finalFileName + fileExtension) + out, err := os.Create(originalFileName + fileExtension) if err != nil { return err } @@ -172,10 +187,5 @@ func applyPatch(test bool, originalFileName, finalFileName, OS string) error { out.Write(finalByte) out.Close() - fmt.Printf("%s successfully patched\n", originalFileName+fileExtension) - if !test { - fmt.Println("Press enter to exit") - fmt.Scanln() - } return nil } diff --git a/patch_test.go b/patch_test.go deleted file mode 100644 index ce0baf3..0000000 --- a/patch_test.go +++ /dev/null @@ -1,48 +0,0 @@ -package main - -import ( - "os" - "testing" -) - -func TestApplyPatchWindows(t *testing.T) { - t.Parallel() - err := backupFile("./test_files/eu4_original.exe", "./test_files/eu4_test.exe") - - if err != nil { - t.Error(err) - } - err = applyPatch(true, "./test_files/eu4_test", "./test_files/eu4_test", "windows") - - if err != nil { - t.Error(err) - } - - if !compareExes("./test_files/eu4_patched.exe", "./test_files/eu4_test.exe") { - if err != nil { - t.Error("Executables doesnt match") - } - } - os.Remove("./test_files/eu4_test.exe") -} - -func TestApplyPatchLinux(t *testing.T) { - t.Parallel() - err := backupFile("./test_files/eu4_original", "./test_files/eu4_test") - - if err != nil { - t.Error(err) - } - err = applyPatch(true, "./test_files/eu4_test", "./test_files/eu4_test", "linux") - if err != nil { - t.Error(err) - } - - if !compareExes("./test_files/eu4_patched", "./test_files/eu4_test") { - if err != nil { - t.Error("Executables doesnt match") - } - } - os.Remove("./test_files/eu4_test") - -} diff --git a/test_eu4_patch_test.go b/test_eu4_patch_test.go new file mode 100644 index 0000000..aa59301 --- /dev/null +++ b/test_eu4_patch_test.go @@ -0,0 +1,50 @@ +package main + +import ( + "os" + "testing" +) + +func TestApplyPatchEU4Windows(t *testing.T) { + err := backupFile("./test_files/eu4/eu4_original.exe", "./test_files/eu4/eu4_test.exe") + + if err != nil { + t.Error(err) + } + err = applyPatch(true, "./test_files/eu4/eu4_test", "windows") + + if err != nil { + t.Error(err) + } + + if !compareExes("./test_files/eu4/eu4_patched.exe", "./test_files/eu4/eu4_test.exe") { + if err != nil { + t.Error("Executables doesnt match") + } + } + os.Remove("./test_files/eu4/eu4_test.exe") + os.Remove("./test_files/eu4/eu4_test_backup.exe") + os.Remove("./test_files/eu4/eu4.exe") +} + +func TestApplyPatchEU4Linux(t *testing.T) { + err := backupFile("./test_files/eu4/eu4_original", "./test_files/eu4/eu4_test") + + if err != nil { + t.Error(err) + } + err = applyPatch(true, "./test_files/eu4/eu4_test", "linux") + if err != nil { + t.Error(err) + } + + if !compareExes("./test_files/eu4/eu4_patched", "./test_files/eu4/eu4_test") { + if err != nil { + t.Error("Executables doesnt match") + } + } + os.Remove("./test_files/eu4/eu4_test") + os.Remove("./test_files/eu4/eu4_test_backup") + os.Remove("./test_files/eu4/eu4") + +} diff --git a/test_hoi4_patch_test.go b/test_hoi4_patch_test.go new file mode 100644 index 0000000..7a7c20c --- /dev/null +++ b/test_hoi4_patch_test.go @@ -0,0 +1,50 @@ +package main + +import ( + "os" + "testing" +) + +func TestApplyPatchHOI4Windows(t *testing.T) { + err := backupFile("./test_files/hoi4/hoi4_original.exe", "./test_files/hoi4/hoi4_test.exe") + + if err != nil { + t.Error(err) + } + err = applyPatch(true, "./test_files/hoi4/hoi4_test", "windows") + + if err != nil { + t.Error(err) + } + + if !compareExes("./test_files/hoi4/hoi4_patched.exe", "./test_files/hoi4/hoi4_test.exe") { + if err != nil { + t.Error("Executables doesnt match") + } + } + os.Remove("./test_files/hoi4/hoi4_test.exe") + os.Remove("./test_files/hoi4/hoi4_test_backup.exe") + os.Remove("./test_files/hoi4/hoi4.exe") +} + +// func TestApplyPatchHOILinux(t *testing.T) { +// err := backupFile("./test_files/hoi4/hoi4_original", "./test_files/hoi4/hoi4_test") + +// if err != nil { +// t.Error(err) +// } +// err = applyPatch(true, "./test_files/hoi4/hoi4_test", "linux") +// if err != nil { +// t.Error(err) +// } + +// if !compareExes("./test_files/hoi4/hoi4_patched", "./test_files/hoi4/hoi4_test") { +// if err != nil { +// t.Error("Executables doesnt match") +// } +// } +// os.Remove("./test_files/hoi4/hoi4_test") +// os.Remove("./test_files/hoi4/hoi4_test_backup") +// os.Remove("./test_files/hoi4/hoi4") + +// }