mirror of https://github.com/zellyn/diskii.git
102 lines
2.9 KiB
Go
102 lines
2.9 KiB
Go
package cmd
|
|
|
|
import (
|
|
"fmt"
|
|
"path"
|
|
"strings"
|
|
|
|
"github.com/zellyn/diskii/disk"
|
|
"github.com/zellyn/diskii/helpers"
|
|
"github.com/zellyn/diskii/types"
|
|
)
|
|
|
|
type ReorderCmd struct {
|
|
Order string `kong:"default='auto',enum='auto,do,po',help='Logical-to-physical sector order.'"`
|
|
NewOrder string `kong:"default='auto',enum='auto,do,po',help='New Logical-to-physical sector order.'"`
|
|
Force bool `kong:"short='s',help='Overwrite existing file?'"`
|
|
|
|
DiskImage string `kong:"arg,required,type='existingfile',help='Disk image to read.'"`
|
|
NewDiskImage string `kong:"arg,optional,type='path',help='Disk image to write, if different.'"`
|
|
}
|
|
|
|
func (r *ReorderCmd) Run(globals *types.Globals) error {
|
|
fromOrderName, toOrderName, err := getOrders(r.DiskImage, r.Order, r.NewDiskImage, r.NewOrder)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
frombytes, err := helpers.FileContentsOrStdIn(r.DiskImage)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
fromOrder, ok := disk.LogicalToPhysicalByName[fromOrderName]
|
|
if !ok {
|
|
return fmt.Errorf("internal error: disk order '%s' not found", fromOrderName)
|
|
}
|
|
toOrder, ok := disk.PhysicalToLogicalByName[toOrderName]
|
|
if !ok {
|
|
return fmt.Errorf("internal error: disk order '%s' not found", toOrderName)
|
|
}
|
|
rawbytes, err := disk.Swizzle(frombytes, fromOrder)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
tobytes, err := disk.Swizzle(rawbytes, toOrder)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
return helpers.WriteOutput(r.NewDiskImage, tobytes, r.DiskImage, r.Force)
|
|
}
|
|
|
|
// getOrders returns the input order, and the output order.
|
|
func getOrders(inFilename string, inOrder string, outFilename string, outOrder string) (string, string, error) {
|
|
if inOrder == "auto" && outOrder != "auto" {
|
|
return oppositeOrder(outOrder), outOrder, nil
|
|
}
|
|
if outOrder == "auto" && inOrder != "auto" {
|
|
return inOrder, oppositeOrder(inOrder), nil
|
|
}
|
|
if inOrder != outOrder {
|
|
return inOrder, outOrder, nil
|
|
}
|
|
if inOrder != "auto" {
|
|
return "", "", fmt.Errorf("identical order and new-order")
|
|
}
|
|
|
|
inGuess, outGuess := orderFromFilename(inFilename), orderFromFilename(outFilename)
|
|
if inGuess == outGuess {
|
|
if inGuess == "" {
|
|
return "", "", fmt.Errorf("cannot determine input or output order from file extensions")
|
|
}
|
|
return "", "", fmt.Errorf("guessed order (%s) from file %q is the same as guessed order (%s) from file %q", inGuess, inFilename, outGuess, outFilename)
|
|
}
|
|
|
|
if inGuess == "" {
|
|
return oppositeOrder(outGuess), outGuess, nil
|
|
}
|
|
if outGuess == "" {
|
|
return inGuess, oppositeOrder(inGuess), nil
|
|
}
|
|
return inGuess, outGuess, nil
|
|
}
|
|
|
|
// oppositeOrder returns the opposite order from the input.
|
|
func oppositeOrder(order string) string {
|
|
if order == "do" {
|
|
return "po"
|
|
}
|
|
return "do"
|
|
}
|
|
|
|
// orderFromFilename tries to guess the disk order from the filename, using the extension.
|
|
func orderFromFilename(filename string) string {
|
|
ext := strings.ToLower(path.Ext(filename))
|
|
switch ext {
|
|
case ".dsk", ".do":
|
|
return "do"
|
|
case ".po":
|
|
return "po"
|
|
default:
|
|
return ""
|
|
}
|
|
}
|