Skip to content

Commit

Permalink
textures: support batch operations
Browse files Browse the repository at this point in the history
  • Loading branch information
halamix2 committed Mar 26, 2023
1 parent cca356b commit 41ac1a8
Show file tree
Hide file tree
Showing 7 changed files with 247 additions and 177 deletions.
85 changes: 49 additions & 36 deletions cmd/pc_pack/pc_pack.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ import (
"strings"

"github.com/halamix2/stunt_gp_tools/pkg/texture"
"github.com/spf13/cobra"
"github.com/spf13/pflag"
)

// flags
Expand All @@ -26,70 +26,83 @@ var (
dreamcast, uncompressed bool
)

var rootCmd = &cobra.Command{
Use: "pack",
Short: "Packs image to texture format used by Stunt GP",
Long: `Packs image to texture format used by Stunt GP
It can pack to either PC or Dreamcast versions of the format
or make uncompressed files if the need arises.`,
Args: cobra.ExactArgs(1),
Run: func(cmd *cobra.Command, args []string) {
inputName := args[0]
if outputName == "" {
func parseFlags() {
pflag.StringVarP(&outputName, "output", "o", "", "name of the output file")
pflag.BoolVarP(&dreamcast, "dreamcast", "d", false, "Packs texture for use in Dreamcast version ")
pflag.BoolVarP(&uncompressed, "uncompressed", "u", false, "Do not compress texture")
pflag.Parse()
}

func usage() {
fmt.Println("Packs image to texture format used by Stunt GP")
// TODO
//fmt.Println("Usage:\npc_pack ")
fmt.Println("Flags:")
pflag.PrintDefaults()
}

func main() {
parseFlags()
args := pflag.Args()
if len(args) < 1 {
usage()
os.Exit(1)
}

if outputName != "" && len(args) > 1 {
fmt.Println("Output name can only be used with one input file")
usage()
os.Exit(1)
}

for _, inputName := range args {
if outputName == "" || len(args) > 1 {
outputName = strings.TrimSuffix(inputName, filepath.Ext(inputName)) + ".pc"
}

fmt.Printf("Hi, today I'll pack %s...\n", inputName)

// deepcode ignore PT: this is a CLI tool
file, err := os.Open(inputName)
if err != nil {
fmt.Fprintf(os.Stderr, "Couldn't open file %s!\n", inputName)
os.Exit(3)
}
defer file.Close()

img, _, err := image.Decode(file)
if err != nil {
fmt.Fprintf(os.Stderr, "Couldn't read image file %s!\n", inputName)
os.Exit(4)
}

err = file.Close()
if err != nil {
fmt.Fprintf(os.Stderr, "Couldn't close image file %s: %s\n", inputName, err)
os.Exit(4)
}

outputFile, err := os.Create(outputName)
if err != nil {
fmt.Fprintf(os.Stderr, "Couldn't create output image file %s!\n", outputName)
os.Exit(4)
}
defer outputFile.Close()

textureFormat := texture.FPC
if dreamcast {
textureFormat = texture.FDreamcast
}
fmt.Printf("packing %s...\n", outputName)
enc := texture.Encoder{Compress: !uncompressed, Dreamcast: dreamcast}
enc := texture.Encoder{Compress: !uncompressed, Format: textureFormat}
err = enc.Encode(outputFile, img)
if err != nil {
fmt.Fprintf(os.Stderr, "Couldn't pack output image %s!\n", outputName)
os.Exit(5)
}
fmt.Println("done")
},
}

func main() {
if err := rootCmd.Execute(); err != nil {
fmt.Println(err)
os.Exit(1)
err = outputFile.Close()
if err != nil {
fmt.Fprintf(os.Stderr, "Couldn't close image file %s: %s\n", outputName, err)
os.Exit(4)
}
}
}

func init() {
cobra.MousetrapHelpText = ""
// Here you will define your flags and configuration settings.
// Cobra supports persistent flags, which, if defined here,
// will be global for your application.

// rootCmd.PersistentFlags().StringVar(&cfgFile, "config", "", "config file (default is $HOME/.test_cobra.yaml)")

// Cobra also supports local flags, which will only run
// when this action is called directly.
rootCmd.Flags().StringVarP(&outputName, "output", "o", "", "name of the output file")
rootCmd.Flags().BoolVarP(&dreamcast, "dreamcast", "d", false, "Packs texture for use in Dreamcast version ")
rootCmd.Flags().BoolVarP(&uncompressed, "uncompressed", "u", false, "Do not compress texture")
}
81 changes: 48 additions & 33 deletions cmd/pc_unpack/pc_unpack.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,35 +17,49 @@ import (
"strings"

"github.com/halamix2/stunt_gp_tools/pkg/texture"
"github.com/spf13/cobra"
"github.com/spf13/pflag"
)

// flags
var (
outputName string
)

var rootCmd = &cobra.Command{
Use: "pack",
Short: "Packs image to texture format used by Stunt GP",
Long: `Packs image to texture format used by Stunt GP
It can pack to either PC or Dreamcast versions of the format
or make uncompressed files if the need arises.`,
Args: cobra.ExactArgs(1),
Run: func(cmd *cobra.Command, args []string) {
inputName := args[0]
if outputName == "" {
func parseFlags() {
pflag.StringVarP(&outputName, "output", "o", "", "name of the output file")
pflag.Parse()
}

func usage() {
fmt.Println("Unpacks image from texture format used by Stunt GP")
// TODO
//fmt.Println("Usage:\npc_unpack ")
fmt.Println("Flags:")
pflag.PrintDefaults()
}

func main() {
parseFlags()
args := pflag.Args()
if len(args) < 1 {
usage()
os.Exit(1)
}

for _, inputName := range args {

if outputName == "" || len(args) > 1 {
outputName = strings.TrimSuffix(inputName, filepath.Ext(inputName)) + ".png"
}

fmt.Printf("Hi, today I'll unpack %s...\n", inputName)

// deepcode ignore PT: this is a CLI tool
file, err := os.Open(inputName)
if err != nil {
fmt.Fprintf(os.Stderr, "Couldn't open file %s!\nReason: %s\n", inputName, err)
os.Exit(3)
}
defer file.Close()

config, format, err := image.DecodeConfig(file)
if err != nil {
Expand All @@ -54,20 +68,29 @@ var rootCmd = &cobra.Command{
}
fmt.Println("Width:", config.Width, "Height:", config.Height, "Format:", format)

file.Seek(0, 0)
_, err = file.Seek(0, 0)
if err != nil {
fmt.Fprintf(os.Stderr, "Couldn't seek in image file %s: %s\n", inputName, err)
os.Exit(4)
}

img, _, err := image.Decode(file)
if err != nil {
fmt.Fprintf(os.Stderr, "Couldn't read image file %s!\nReason: %s\n", inputName, err)
os.Exit(4)
}

err = file.Close()
if err != nil {
fmt.Fprintf(os.Stderr, "Couldn't close image file %s: %s\n", inputName, err)
os.Exit(4)
}

outputFile, err := os.Create(outputName)
if err != nil {
fmt.Fprintf(os.Stderr, "Couldn't create output image file %s!\nReason: %s\n", outputName, err)
os.Exit(4)
}
defer outputFile.Close()

ext := filepath.Ext(strings.ToLower(outputName))
switch ext {
Expand All @@ -80,6 +103,12 @@ var rootCmd = &cobra.Command{
err = png.Encode(outputFile, img)
case ".pc":
err = texture.Encode(outputFile, img)
case ".dc":
encoder := texture.Encoder{
Compress: true,
Format: texture.FDreamcast,
}
err = encoder.Encode(outputFile, img)
default:
err = errors.New("unknown output format")
}
Expand All @@ -88,25 +117,11 @@ var rootCmd = &cobra.Command{
fmt.Fprintf(os.Stderr, "Couldn't pack output image %s!\nReason: %s\n", outputName, err)
os.Exit(5)
}
},
}

func main() {
if err := rootCmd.Execute(); err != nil {
fmt.Println(err)
os.Exit(1)
err = outputFile.Close()
if err != nil {
fmt.Fprintf(os.Stderr, "Couldn't close image file %s: %s\n", outputName, err)
os.Exit(4)
}
}
}

func init() {
cobra.MousetrapHelpText = ""
// Here you will define your flags and configuration settings.
// Cobra supports persistent flags, which, if defined here,
// will be global for your application.

// rootCmd.PersistentFlags().StringVar(&cfgFile, "config", "", "config file (default is $HOME/.test_cobra.yaml)")

// Cobra also supports local flags, which will only run
// when this action is called directly.
rootCmd.Flags().StringVarP(&outputName, "output", "o", "", "name of the output file")
}
3 changes: 0 additions & 3 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,5 @@ go 1.19

require (
github.com/gojuno/go.morton v0.0.0-20180202102823-94709bd871ce
github.com/spf13/cobra v1.6.1
github.com/spf13/pflag v1.0.5
)

require github.com/inconshreveable/mousetrap v1.0.1 // indirect
8 changes: 0 additions & 8 deletions go.sum
Original file line number Diff line number Diff line change
@@ -1,12 +1,4 @@
github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
github.com/gojuno/go.morton v0.0.0-20180202102823-94709bd871ce h1:mUc5xcG/z3O9Y0Ic2P0dpoDIM56SVM22HOS91duNaWQ=
github.com/gojuno/go.morton v0.0.0-20180202102823-94709bd871ce/go.mod h1:kJO7W3iXPkHAnBENPwQxLWhBV9IjKqdhjGOA4Yy/f5E=
github.com/inconshreveable/mousetrap v1.0.1 h1:U3uMjPSQEBMNp1lFxmllqCPM6P5u/Xq7Pgzkat/bFNc=
github.com/inconshreveable/mousetrap v1.0.1/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/spf13/cobra v1.6.1 h1:o94oiPyS4KD1mPy2fmcYYHHfCxLqYjJOhGsCHFZtEzA=
github.com/spf13/cobra v1.6.1/go.mod h1:IOw/AERYS7UzyrGinqmz6HLUo219MORXGxhbaJUqzrY=
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
27 changes: 27 additions & 0 deletions pkg/texture/common.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package texture

import (
"encoding/binary"
"io"
)

const textureHeader = "TM!\x1a"

// TODO there's gotta be a better way
const (
FIncorrect = iota // we''ll default to FPC
// TODO check PS2/prototype versions for this
FUnknown // we don't have any examples of these textures at all
FPaletted // paletted images used by PS2
FPC // Windows version
FDreamcast // Dreamcast swizzled textures
FPSTwo // PS2 textures with swapped R B channels
)

func getWord(r io.Reader) (uint16, error) {
buf := make([]byte, 2)
if _, err := io.ReadFull(r, buf); err != nil {
return 0, err
}
return binary.LittleEndian.Uint16(buf), nil
}
Loading

0 comments on commit 41ac1a8

Please sign in to comment.