Skip to content

Commit

Permalink
Hearts of Iron IV support, rename repo
Browse files Browse the repository at this point in the history
  • Loading branch information
IlliaYalovoi committed Jun 20, 2023
1 parent 028c9b3 commit 49cf18b
Show file tree
Hide file tree
Showing 8 changed files with 197 additions and 90 deletions.
4 changes: 2 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
@@ -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
env GOOS=linux GOARCH=amd64 go build -o ./build/universal-checksum-patcher-linux *.go
7 changes: 7 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
@@ -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
)
10 changes: 10 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
@@ -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=
36 changes: 32 additions & 4 deletions main.go
Original file line number Diff line number Diff line change
@@ -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()

}
82 changes: 46 additions & 36 deletions patch.go
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand All @@ -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 == "??" {
Expand All @@ -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
Expand All @@ -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) {
Expand All @@ -140,42 +161,31 @@ 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
}

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
}
48 changes: 0 additions & 48 deletions patch_test.go

This file was deleted.

50 changes: 50 additions & 0 deletions test_eu4_patch_test.go
Original file line number Diff line number Diff line change
@@ -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")

}
50 changes: 50 additions & 0 deletions test_hoi4_patch_test.go
Original file line number Diff line number Diff line change
@@ -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")

// }

0 comments on commit 49cf18b

Please sign in to comment.