Skip to content

Commit

Permalink
feat: add ROM conversion command
Browse files Browse the repository at this point in the history
  • Loading branch information
mroach committed Aug 15, 2021
1 parent aedcbf5 commit 781b4a0
Show file tree
Hide file tree
Showing 3 changed files with 128 additions and 29 deletions.
51 changes: 51 additions & 0 deletions cmd/convert.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
package cmd

import (
"errors"
"fmt"
"os"
"path"
"strings"

"github.com/mroach/n64-go/rom"
"github.com/spf13/cobra"
)

func init() {
var overwrite bool
var convertCmd = &cobra.Command{
Use: "convert",
Short: "Converts a ROM to native Big-Endian Z64 format",
Args: cobra.MinimumNArgs(1),
RunE: func(cmd *cobra.Command, args []string) error {
inpath := args[0]
dirname, filename := path.Split(inpath)
baseFilename := basename(filename)
outFilename := baseFilename + ".z64"
outpath := path.Join(dirname, outFilename)

if !overwrite {
if _, err := os.Stat(outpath); err == nil {
return errors.New(outpath + " already exists")
}
}

if err := rom.ConvertRomFormat(inpath, outpath); err != nil {
return err
}

fmt.Println(inpath, "=>", outpath)
return nil
},
}

convertCmd.Flags().BoolVarP(&overwrite, "force", "f", false, "Overwrite destination file if it exists")
rootCmd.AddCommand(convertCmd)
}

func basename(filename string) string {
if pos := strings.LastIndexByte(filename, '.'); pos != -1 {
return filename[:pos]
}
return filename
}
77 changes: 77 additions & 0 deletions rom/convert.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
package rom

import (
"errors"
"io"
"os"
)

func ConvertRomFormat(inpath string, outpath string) error {
const bufferSize = 2048

info, err := FromPath(inpath)
if err != nil {
return err
}

if info.File.Format == "z64" {
return errors.New("File is already in the native Z64 format")
}

source, err := os.Open(inpath)
if err != nil {
return err
}

dest, err := os.Create(outpath)
if err != nil {
return err
}

for {
buf := make([]byte, bufferSize)
n, err := source.Read(buf)
if err != nil && err != io.EOF {
return err
}
if n == 0 {
break
}

buf = maybeReverseBytes(buf, info.File.Format)
if _, err := dest.Write(buf[:n]); err != nil {
return err
}
}

return nil
}

func maybeReverseBytes(bytes []byte, romFormat string) []byte {
if romFormat == "v64" {
return reverseBytes(bytes, 2)
}

if romFormat == "n64" {
return reverseBytes(bytes, 4)
}

return bytes
}

func reverseBytes(bytes []byte, size int) (reversed []byte) {
for _, chunk := range chunk(bytes, size) {
for i := len(chunk) - 1; i >= 0; i = i - 1 {
reversed = append(reversed, chunk[i])
}
}

return reversed
}

func chunk(bytes []byte, chunkSize int) (chunks [][]byte) {
for chunkSize < len(bytes) {
bytes, chunks = bytes[chunkSize:], append(chunks, bytes[0:chunkSize:chunkSize])
}
return append(chunks, bytes)
}
29 changes: 0 additions & 29 deletions rom/rom.go
Original file line number Diff line number Diff line change
Expand Up @@ -224,35 +224,6 @@ func detectRomFormat(signature []byte) (string, error) {
return "", errors.New("Unknown ROM format. Invalid file?")
}

func maybeReverseBytes(bytes []byte, romFormat string) []byte {
if romFormat == "v64" {
return reverseBytes(bytes, 2)
}

if romFormat == "n64" {
return reverseBytes(bytes, 4)
}

return bytes
}

func reverseBytes(bytes []byte, size int) (reversed []byte) {
for _, chunk := range chunk(bytes, size) {
for i := len(chunk) - 1; i >= 0; i = i - 1 {
reversed = append(reversed, chunk[i])
}
}

return reversed
}

func chunk(bytes []byte, chunkSize int) (chunks [][]byte) {
for chunkSize < len(bytes) {
bytes, chunks = bytes[chunkSize:], append(chunks, bytes[0:chunkSize:chunkSize])
}
return append(chunks, bytes)
}

func bytesToString(bytes []byte) string {
chars := []rune{}

Expand Down

0 comments on commit 781b4a0

Please sign in to comment.