Skip to content

Commit

Permalink
Refactor
Browse files Browse the repository at this point in the history
  • Loading branch information
xypwn committed Apr 29, 2024
1 parent 5d62c24 commit a1821f1
Show file tree
Hide file tree
Showing 6 changed files with 105 additions and 136 deletions.
148 changes: 58 additions & 90 deletions app/app.go
Original file line number Diff line number Diff line change
Expand Up @@ -79,21 +79,35 @@ var ConfigFormat = ConfigTemplate{
Fallback: "raw",
}

type App struct {
Hashes map[stingray.Hash]string
gameDir string
dataDir *stingray.DataDir
}

func New() *App {
a := &App{
Hashes: make(map[stingray.Hash]string),
func parseWwiseDep(f *stingray.File) (string, error) {
r, err := f.Open(stingray.DataMain)
if err != nil {
return "", err
}
var magicNum [4]byte
if _, err := io.ReadFull(r, magicNum[:]); err != nil {
return "", err
}
if magicNum != [4]byte{0xd8, '/', 'v', 'x'} {
return "", errors.New("invalid magic number")
}
var textLen uint32
if err := binary.Read(r, binary.LittleEndian, &textLen); err != nil {
return "", err
}
text := make([]byte, textLen-1)
if _, err := io.ReadFull(r, text); err != nil {
return "", err
}
return string(text), nil
}

return a
// Returns error if steam path couldn't be found.
func DetectGameDir() (string, error) {
return steampath.GetAppPath("553850", "Helldivers 2")
}

func (a *App) SetGameDir(path string) error {
func VerifyGameDir(path string) error {
if info, err := os.Stat(path); err != nil || !info.IsDir() {
return fmt.Errorf("invalid game directory: %v: not a directory", path)
}
Expand All @@ -104,94 +118,52 @@ func (a *App) SetGameDir(path string) error {
if info, err := os.Stat(filepath.Join(path, "data", "settings.ini")); err != nil || !info.Mode().IsRegular() {
return fmt.Errorf("invalid game directory: %v: valid data directory not found", path)
}
path, err := filepath.Abs(path)
if err != nil {
return err
}
a.gameDir = path
return nil
}

func (a *App) DetectGameDir() (string, error) {
path, err := steampath.GetAppPath("553850", "Helldivers 2")
if err != nil {
return "", err
}
if err := a.SetGameDir(path); err != nil {
return "", err
func ParseHashes(str string) []string {
var res []string
sc := bufio.NewScanner(strings.NewReader(str))
for sc.Scan() {
s := strings.TrimSpace(sc.Text())
if s != "" && !strings.HasPrefix(s, "//") {
res = append(res, s)
}
}
return path, nil
return res
}

type App struct {
Hashes map[stingray.Hash]string
DataDir *stingray.DataDir
}

func (a *App) OpenGameDir() error {
dataDir, err := stingray.OpenDataDir(filepath.Join(a.gameDir, "data"))
// Open game dir and read metadata.
func New(gameDir string, hashes []string) (*App, error) {
dataDir, err := stingray.OpenDataDir(filepath.Join(gameDir, "data"))
if err != nil {
return err
return nil, err
}
a.dataDir = dataDir

hashesMap := make(map[stingray.Hash]string)
for _, h := range hashes {
hashesMap[stingray.Sum64([]byte(h))] = h
}
// wwise_dep files let us know the string of many of the wwise_banks
for id, file := range dataDir.Files {
if id.Type == stingray.Sum64([]byte("wwise_dep")) {
if err := a.addHashFromWwiseDep(*file); err != nil {
return fmt.Errorf("wwise_dep: %w", err)
h, err := parseWwiseDep(file)
if err != nil {
return nil, fmt.Errorf("wwise_dep: %w", err)
}
hashesMap[stingray.Sum64([]byte(h))] = h
}
}

return nil
}

func (a *App) addHashFromWwiseDep(f stingray.File) error {
r, err := f.Open(stingray.DataMain)
if err != nil {
return err
}
var magicNum [4]byte
if _, err := io.ReadFull(r, magicNum[:]); err != nil {
return err
}
if magicNum != [4]byte{0xd8, '/', 'v', 'x'} {
return errors.New("invalid magic number")
}
var textLen uint32
if err := binary.Read(r, binary.LittleEndian, &textLen); err != nil {
return err
}
text := make([]byte, textLen-1)
if _, err := io.ReadFull(r, text); err != nil {
return err
}
a.AddHashFromString(string(text))
return nil
}

func (a *App) AddHashFromString(str string) {
a.Hashes[stingray.Sum64([]byte(str))] = str
}

func (a *App) AddHashesFromString(str string) {
sc := bufio.NewScanner(strings.NewReader(str))
for sc.Scan() {
s := strings.TrimSpace(sc.Text())
if s != "" && !strings.HasPrefix(s, "//") {
a.AddHashFromString(s)
}
}
}

func (a *App) AddHashesFromFile(path string) error {
b, err := os.ReadFile(path)
if err != nil {
return err
}
a.AddHashesFromString(string(b))
return nil
}

func (a *App) File(id stingray.FileID) (f *stingray.File, exists bool) {
f, exists = a.dataDir.Files[id]
return
return &App{
Hashes: hashesMap,
DataDir: dataDir,
}, nil
}

func (a *App) matchFileID(id stingray.FileID, glb glob.Glob, nameOnly bool) bool {
Expand Down Expand Up @@ -235,10 +207,6 @@ func (a *App) matchFileID(id stingray.FileID, glb glob.Glob, nameOnly bool) bool
return false
}

func (a *App) AllFiles() map[stingray.FileID]*stingray.File {
return a.dataDir.Files
}

func (a *App) MatchingFiles(includeGlob, excludeGlob string, cfgTemplate ConfigTemplate, cfg map[string]map[string]string) (map[stingray.FileID]*stingray.File, error) {
var inclGlob glob.Glob
inclGlobNameOnly := !strings.Contains(includeGlob, ".")
Expand All @@ -260,7 +228,7 @@ func (a *App) MatchingFiles(includeGlob, excludeGlob string, cfgTemplate ConfigT
}

res := make(map[stingray.FileID]*stingray.File)
for id, file := range a.dataDir.Files {
for id, file := range a.DataDir.Files {
shouldIncl := true
if includeGlob != "" {
shouldIncl = a.matchFileID(id, inclGlob, inclGlobNameOnly)
Expand Down Expand Up @@ -327,7 +295,7 @@ func (c *extractContext) File() *stingray.File { return c.file }
func (c *extractContext) Runner() *exec.Runner { return c.runner }
func (c *extractContext) Config() map[string]string { return c.config }
func (c *extractContext) GetResource(name, typ stingray.Hash) (file *stingray.File, exists bool) {
file, exists = c.app.AllFiles()[stingray.FileID{Name: name, Type: typ}]
file, exists = c.app.DataDir.Files[stingray.FileID{Name: name, Type: typ}]
return
}
func (c *extractContext) CreateFile(suffix string) (io.WriteCloser, error) {
Expand All @@ -352,7 +320,7 @@ func (a *App) ExtractFile(id stingray.FileID, outDir string, extrCfg map[string]
typ = id.Type.String()
}

file, ok := a.dataDir.Files[id]
file, ok := a.DataDir.Files[id]
if !ok {
return fmt.Errorf("extract %v.%v: file does not found", name, typ)
}
Expand Down
27 changes: 14 additions & 13 deletions cmd/filediver-cli/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -84,38 +84,39 @@ extractor config:
}
defer runner.Close()

a := app.New()

if *gameDir == "" {
if path, err := a.DetectGameDir(); err == nil {
prt.Infof("Using game found at: \"%v\"", path)
var err error
*gameDir, err = app.DetectGameDir()
if err == nil {
prt.Infof("Using game found at: \"%v\"", *gameDir)
} else {
prt.Errorf("Helldivers 2 Steam installation path not found: %v", err)
prt.Fatalf("Unable to detect game install directory. Please specify the game directory manually using the '-g' option.")
}
} else {
if err := a.SetGameDir(*gameDir); err != nil {
prt.Fatalf("%v", err)
}
prt.Infof("Game directory: \"%v\"", *gameDir)
}

if *knownHashesPath == "" {
a.AddHashesFromString(hashes.Hashes)
} else {
if err := a.AddHashesFromFile(*knownHashesPath); err != nil {
var knownHashes []string
knownHashes = append(knownHashes, app.ParseHashes(hashes.Hashes)...)
if *knownHashesPath != "" {
b, err := os.ReadFile(*knownHashesPath)
if err != nil {
prt.Fatalf("%v", err)
}
knownHashes = append(knownHashes, app.ParseHashes(string(b))...)
}

if !*modeList {
prt.Infof("Output directory: \"%v\"", *outDir)
}

prt.Infof("Reading metadata...")
if err := a.OpenGameDir(); err != nil {
a, err := app.New(*gameDir, knownHashes)
if err != nil {
prt.Fatalf("%v", err)
}

files, err := a.MatchingFiles(*extrInclGlob, *extrExclGlob, app.ConfigFormat, extrCfg)
if err != nil {
prt.Fatalf("%v", err)
Expand Down Expand Up @@ -144,7 +145,7 @@ extractor config:
{
names := make(map[stingray.Hash]struct{})
types := make(map[stingray.Hash]struct{})
for id := range a.AllFiles() {
for id := range a.DataDir.Files {
names[id.Name] = struct{}{}
types[id.Type] = struct{}{}
}
Expand Down
14 changes: 7 additions & 7 deletions exec/exec_all.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
//go:build !windows

package exec

import "os/exec"

func applyOSSpecificCmdOpts(cmd *exec.Cmd) {}
//go:build !windows

package exec

import "os/exec"

func applyOSSpecificCmdOpts(cmd *exec.Cmd) {}
24 changes: 12 additions & 12 deletions exec/exec_windows.go
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
//go:build windows

package exec

import (
"os/exec"
"syscall"
)

func applyOSSpecificCmdOpts(cmd *exec.Cmd) {
cmd.SysProcAttr = &syscall.SysProcAttr{HideWindow: true}
}
//go:build windows

package exec

import (
"os/exec"
"syscall"
)

func applyOSSpecificCmdOpts(cmd *exec.Cmd) {
cmd.SysProcAttr = &syscall.SysProcAttr{HideWindow: true}
}
6 changes: 3 additions & 3 deletions hashes/generate.go
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
package hashes

//go:generate go run github.com/xypwn/filediver/hashes/generate
package hashes

//go:generate go run github.com/xypwn/filediver/hashes/generate
22 changes: 11 additions & 11 deletions hashes/hashes.go
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
package hashes

import (
_ "embed"
)

//go:embed hashes.txt
var Hashes string

//go:embed material_textures.txt
var MaterialTextures string
package hashes

import (
_ "embed"
)

//go:embed hashes.txt
var Hashes string

//go:embed material_textures.txt
var MaterialTextures string

0 comments on commit a1821f1

Please sign in to comment.