diff --git a/cmd/script-decode.go b/cmd/script-decode.go index 04bde2d..722a146 100644 --- a/cmd/script-decode.go +++ b/cmd/script-decode.go @@ -5,8 +5,11 @@ import ( "os" "strings" "strconv" + "bufio" + "slices" "github.com/alexflint/go-arg" + "git.zorchenhimer.com/Zorchenhimer/go-studybox/script" ) @@ -14,6 +17,8 @@ type Arguments struct { Input string `arg:"positional,required"` Output string `arg:"positional"` StartAddr string `arg:"--start" default:"0x6000" help:"base address for the start of the script"` + LabelFile string `arg:"--labels" help:"file containing address/label pairs"` + start int } @@ -38,6 +43,18 @@ func run(args *Arguments) error { return err } + if args.LabelFile != "" { + labels, err := parseLabelFile(args.LabelFile) + if err != nil { + return err + } + + for _, label := range labels { + //fmt.Printf("%#v\n", label) + scr.Labels[label.Address] = label + } + } + outfile := os.Stdout if args.Output != "" { outfile, err = os.Create(args.Output) @@ -64,6 +81,62 @@ func run(args *Arguments) error { return nil } +func parseLabelFile(filename string) ([]*script.Label, error) { + file, err := os.Open(filename) + if err != nil { + return nil, err + } + defer file.Close() + + labels := []*script.Label{} + scanner := bufio.NewScanner(file) + for scanner.Scan() { + line := strings.TrimSpace(scanner.Text()) + if line == "" || strings.HasPrefix(line, "#") { + continue + } + + line = strings.ReplaceAll(line, "\t", " ") + parts := strings.Split(line, " ") + + parts = slices.DeleteFunc(parts, func(str string) bool { + return str == "" + }) + + if len(parts) < 2 { + fmt.Println("Ignoring", line) + continue + } + + if strings.HasPrefix(parts[0], "$") { + parts[0] = "0x"+parts[0][1:] + } + + addr, err := strconv.ParseInt(parts[0], 0, 32) + if err != nil { + fmt.Printf("Address parse error for %q: %s\n", line, err) + continue + } + + lbl := &script.Label{ + Name: parts[1], + Address: int(addr), + } + + if lbl.Name == "$" { + lbl.Name = "" + } + + if len(parts) > 2 { + lbl.Comment = strings.Join(parts[2:], " ") + } + + labels = append(labels, lbl) + } + + return labels, nil +} + func main() { args := &Arguments{} arg.MustParse(args) diff --git a/script/parser.go b/script/parser.go index e491ff9..aebc410 100644 --- a/script/parser.go +++ b/script/parser.go @@ -5,6 +5,42 @@ import ( "os" ) +type Label struct { + Address int + Name string + Comment string + FarLabel bool +} + +func AutoLabel(address int) *Label { + return &Label{ + Address: address, + Name: fmt.Sprintf("L%04X", address), + } +} + +func AutoLabelVar(address int) *Label { + return &Label{ + Address: address, + Name: fmt.Sprintf("Var_%04X", address), + } +} + +func AutoLabelFar(address int) *Label { + return &Label{ + Address: address, + Name: fmt.Sprintf("F%04X", address), + FarLabel: true, + } +} + +func NewLabel(address int, name string) *Label { + return &Label{ + Address: address, + Name: name, + } +} + func ParseFile(filename string, startAddr int) (*Script, error) { rawfile, err := os.ReadFile(filename) if err != nil { @@ -24,7 +60,7 @@ func Parse(rawinput []byte, startAddr int) (*Script, error) { Warnings: []string{}, StackAddress: (int(rawinput[1])<<8) | int(rawinput[0]), StartAddress: startAddr, - Labels: make(map[int]string), // map[location]name + Labels: make(map[int]*Label), // map[location]name } tokenMap := make(map[int]*Token) @@ -112,7 +148,7 @@ func Parse(rawinput []byte, startAddr int) (*Script, error) { if tok.Offset == addr { tok.IsTarget = true found = true - script.Labels[addr] = fmt.Sprintf("L%04X", addr) + script.Labels[addr] = AutoLabel(addr) //fmt.Sprintf("L%04X", addr) break } } @@ -133,7 +169,7 @@ func Parse(rawinput []byte, startAddr int) (*Script, error) { if tok.Offset == addr { tok.IsTarget = true found = true - script.Labels[addr] = fmt.Sprintf("L%04X", addr) + script.Labels[addr] = AutoLabel(addr) //fmt.Sprintf("L%04X", addr) break } } @@ -152,7 +188,7 @@ func Parse(rawinput []byte, startAddr int) (*Script, error) { addr := t.Inline[0].Int() if tok, ok := tokenMap[addr]; ok { tok.IsVariable = true - script.Labels[addr] = fmt.Sprintf("Var_%04X", addr) + script.Labels[addr] = AutoLabelVar(addr) //fmt.Sprintf("Var_%04X", addr) } } } diff --git a/script/script.go b/script/script.go index ae8a2dc..35a5693 100644 --- a/script/script.go +++ b/script/script.go @@ -10,5 +10,6 @@ type Script struct { StartAddress int StackAddress int - Labels map[int]string + //Labels map[int]string + Labels map[int]*Label } diff --git a/script/tokens.go b/script/tokens.go index 56a5d9b..2f07b9d 100644 --- a/script/tokens.go +++ b/script/tokens.go @@ -15,7 +15,7 @@ type Token struct { Instruction *Instruction } -func (t Token) String(labels map[int]string) string { +func (t Token) String(labels map[int]*Label) string { suffix := "" switch t.Raw { case 0x86: @@ -25,10 +25,18 @@ func (t Token) String(labels map[int]string) string { prefix := "" if t.IsTarget || t.IsVariable { if lbl, ok := labels[t.Offset]; ok { - prefix = "\n"+lbl+":\n" + comment := "" + if lbl.Comment != "" { + comment = "; "+lbl.Comment+"\n" + } + prefix = "\n"+comment+lbl.Name+":\n" } else { prefix = fmt.Sprintf("\nL%04X:\n", t.Offset) } + } else { + if lbl, ok := labels[t.Offset]; ok && lbl.Comment != "" { + suffix = " ; "+lbl.Comment+suffix + } } if t.Raw < 0x80 { @@ -56,7 +64,7 @@ func (t Token) String(labels map[int]string) string { argstr := []string{} for _, a := range t.Inline { if lbl, ok := labels[a.Int()]; ok { - argstr = append(argstr, lbl) + argstr = append(argstr, lbl.Name) } else { argstr = append(argstr, a.HexString()) }