diff --git a/utils/extract-mpq/doc.go b/utils/extract-mpq/doc.go new file mode 100644 index 00000000..9f8eb89b --- /dev/null +++ b/utils/extract-mpq/doc.go @@ -0,0 +1,13 @@ +// This command line utility provides a way to extract mpq files. +// +// Flags: +// -o [directory] Output directory +// -v Enable verbose output +// +// Usage: +// First run `go install extract-mpq.go` in this directory. +// Navigate to the Diablo II directory (ex: C:/Program Files (x86)/Diablo II) +// then run extract-mpq(.exe) with the filename of the mpq to be extracted. +// +// extract-mpq d2char.mpq +package main diff --git a/utils/extract-mpq/extract-mpq.go b/utils/extract-mpq/extract-mpq.go new file mode 100644 index 00000000..91a9de64 --- /dev/null +++ b/utils/extract-mpq/extract-mpq.go @@ -0,0 +1,79 @@ +package main + +import ( + "flag" + "fmt" + "github.com/OpenDiablo2/OpenDiablo2/d2common/d2interface" + "log" + "os" + "path/filepath" + "strings" + + "github.com/OpenDiablo2/OpenDiablo2/d2common/d2fileformats/d2mpq" +) + +func main() { + var ( + outPath string + verbose bool + ) + flag.StringVar(&outPath, "o", "./output/", "output directory") + flag.BoolVar(&verbose, "v", false, "verbose output") + flag.Parse() + + if len(flag.Args()) != 1 { + fmt.Printf("Usage: %s filename.mpq\n", os.Args[0]) + os.Exit(1) + } + + filename := flag.Arg(0) + mpq, err := d2mpq.Load(filename) + if err != nil { + log.Fatal(err) + } + + list, err := mpq.GetFileList() + if err != nil { + log.Fatal(err) + } + + _, mpqFile := filepath.Split(strings.Replace(filename, "\\", "/", -1)) + for _, filename := range list { + extractFile(mpq, mpqFile, filename, outPath) + + if verbose { + fmt.Printf("Writing: %s\n", filename) + } + } +} + +func extractFile(mpq d2interface.Archive, mpqFile string, filename string, outPath string) { + defer func() { + if r := recover(); r != nil { + log.Printf("recovered from panic in file: %s, %v", filename, r) + } + }() + dir, file := filepath.Split(strings.Replace(filename, "\\", "/", -1)) + dir = mpqFile + "/" + dir + + err := os.MkdirAll(outPath+dir, 0755) + if err != nil { + log.Printf("failed to create directory: %s, %v", outPath+dir, err) + return + } + + f, err := os.Create(outPath + dir + file) + if err != nil { + log.Printf("failed to create file: %s, %v", filename, err) + return + } + defer f.Close() + + buf, err := mpq.ReadFile(filename) + if err != nil { + log.Printf("failed to read file: %s, %v", filename, err) + return + } + f.Write(buf) + +}