Moved --extract to its own utility
fdsextract now handles all extraction stuff. This utility also has more functionality. There are options to extract a single side, a single file on a single side, and an address range from a single file from a single side. Files and sides are 0-indexed.
This commit is contained in:
parent
c2a6fc7fa3
commit
bf2afab07d
3
Makefile
3
Makefile
|
|
@ -1,6 +1,7 @@
|
|||
|
||||
CMDS= \
|
||||
bin/fdslist
|
||||
bin/fdslist \
|
||||
bin/fdsextract
|
||||
|
||||
all: bin $(CMDS)
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,155 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"strconv"
|
||||
|
||||
"github.com/alexflint/go-arg"
|
||||
|
||||
"git.zorchenhimer.com/zorchenhimer/go-fds"
|
||||
)
|
||||
|
||||
type Arguments struct {
|
||||
Input string `arg:"positional,required"`
|
||||
|
||||
// for getting a specific file
|
||||
Side int `arg:"--side" default:"-1"`
|
||||
|
||||
FileNum int `arg:"--file-num" default:"-1"`
|
||||
Range string `arg:"--range"`
|
||||
}
|
||||
|
||||
func main() {
|
||||
args := &Arguments{}
|
||||
arg.MustParse(args)
|
||||
|
||||
err := run(args)
|
||||
if err != nil {
|
||||
fmt.Fprintln(os.Stderr, err)
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
||||
|
||||
func run(args *Arguments) error {
|
||||
rom, err := fds.ReadRomFile(args.Input)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
outdir := strings.TrimSuffix(args.Input, filepath.Ext(args.Input))
|
||||
err = os.MkdirAll(outdir, 0775)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if args.Side >= 0 && args.FileNum == -1 {
|
||||
if args.Side >= len(rom.Sides) {
|
||||
return fmt.Errorf("--side out of range")
|
||||
}
|
||||
|
||||
num := 0
|
||||
for _, s := range rom.Sides[:args.Side] {
|
||||
num += len(s.Files)
|
||||
}
|
||||
|
||||
side := rom.Sides[args.Side]
|
||||
sideName := fmt.Sprintf("Side%d", side.Header.PhysicalSide)
|
||||
for _, file := range side.Files {
|
||||
fileName := filepath.Join(outdir, fmt.Sprintf("%03d_%s_%02d_%02X", num, sideName, file.Number, file.Id))
|
||||
err := os.WriteFile(fileName, file.Data, 0664)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
num++
|
||||
}
|
||||
return nil
|
||||
} else if args.Side >= 0 && args.FileNum >= 0 {
|
||||
if args.Side >= len(rom.Sides) {
|
||||
return fmt.Errorf("--side out of range")
|
||||
}
|
||||
|
||||
side := rom.Sides[args.Side]
|
||||
|
||||
if len(side.Files) <= args.FileNum {
|
||||
return fmt.Errorf("--file-num out of range; %d", len(side.Files))
|
||||
}
|
||||
|
||||
sideName := fmt.Sprintf("Side%d", side.Header.PhysicalSide)
|
||||
file := side.Files[args.FileNum]
|
||||
|
||||
var start int
|
||||
var end int
|
||||
if args.Range != "" {
|
||||
start, end, err = parseRange(args.Range)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
fmt.Printf("start: %04X\nend: %04X\n", start, end)
|
||||
|
||||
start = start - int(file.Address)
|
||||
end = end - int(file.Address)
|
||||
|
||||
fmt.Printf("start: %04X\nend: %04X\n", start, end)
|
||||
|
||||
} else {
|
||||
start = 0
|
||||
end = file.Size
|
||||
}
|
||||
|
||||
fileName := filepath.Join(outdir, fmt.Sprintf("%03d_%s_%02d_%02X", args.FileNum, sideName, file.Number, file.Id))
|
||||
fmt.Println("fileName:", fileName)
|
||||
err := os.WriteFile(fileName, file.Data[start:end], 0664)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
|
||||
} else if args.Range != "" && (args.Side < 0 || args.FileNum < 0) {
|
||||
return fmt.Errorf("--range cannot be given alone")
|
||||
}
|
||||
|
||||
num := 0
|
||||
for _, side := range rom.Sides {
|
||||
sideName := fmt.Sprintf("Side%d", side.Header.PhysicalSide)
|
||||
for _, file := range side.Files {
|
||||
fileName := filepath.Join(outdir, fmt.Sprintf("%03d_%s_%02d_%02X", args.FileNum, sideName, file.Number, file.Id))
|
||||
err := os.WriteFile(fileName, file.Data, 0664)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
num++
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// $6000-$5000
|
||||
func parseRange(input string) (int, int, error) {
|
||||
splits := strings.Split(input, "-")
|
||||
if len(splits) != 2 {
|
||||
return 0, 0, fmt.Errorf("invalid range: %q", input)
|
||||
}
|
||||
fmt.Println("splits:", splits)
|
||||
|
||||
splits[0] = strings.Replace(splits[0], "$", "0x", 1)
|
||||
splits[1] = strings.Replace(splits[1], "$", "0x", 1)
|
||||
|
||||
fmt.Println("splits:", splits)
|
||||
|
||||
start, err := strconv.ParseInt(splits[0], 0, 64)
|
||||
if err != nil {
|
||||
return 0, 0, fmt.Errorf("invalid range: %q", input)
|
||||
}
|
||||
|
||||
end, err := strconv.ParseInt(splits[1], 0, 64)
|
||||
if err != nil {
|
||||
return 0, 0, fmt.Errorf("invalid range: %q", input)
|
||||
}
|
||||
|
||||
return int(start), int(end), nil
|
||||
}
|
||||
Loading…
Reference in New Issue