diff --git a/cmd/script-decode.go b/cmd/script-decode.go index 5856eea..5a4929e 100644 --- a/cmd/script-decode.go +++ b/cmd/script-decode.go @@ -21,6 +21,7 @@ type Arguments struct { StatsFile string `arg:"--stats" help:"file to write some statistics to"` LabelFile string `arg:"--labels" help:"file containing address/label pairs"` CDL string `arg:"--cdl" help:"CodeDataLog json file"` + CDLOutput string `arg:"--cdl-output"` Smart bool `arg:"--smart"` start int @@ -103,10 +104,6 @@ func run(args *Arguments) error { return 0 }) - //for _, lbl := range scr.Labels { - // fmt.Println(lbl) - //} - for _, token := range scr.Tokens { fmt.Fprintln(outfile, token.String(scr.Labels)) } @@ -124,6 +121,22 @@ func run(args *Arguments) error { } } + if scr.CDL != nil { + cdlout := args.CDL + if args.CDLOutput != "" { + cdlout = args.CDLOutput + } + + if cdlout == "" { + return nil + } + + err = scr.CDL.WriteToFile(cdlout) + if err != nil { + return fmt.Errorf("Error writing CDL file: %w", err) + } + } + return nil } diff --git a/script/cdl.go b/script/cdl.go index c773ed1..4d6e7d5 100644 --- a/script/cdl.go +++ b/script/cdl.go @@ -6,6 +6,7 @@ import ( "encoding/json" "strconv" "fmt" + "slices" ) type CodeDataLog struct { @@ -28,8 +29,101 @@ var ( cdlUnknown cdlBit = 0x00 cdlCode cdlBit = 0x01 cdlData cdlBit = 0x02 + //cdlOpCode cdlBit = 0x04 ) +func (cdl *CodeDataLog) WriteToFile(filename string) error { + file, err := os.Create(filename) + if err != nil { + return err + } + + _, werr := cdl.WriteTo(file) + err = file.Close() + if err != nil { + return err + } + + return werr +} + +func getRanges(list []int) []CdlRange { + //fmt.Printf("getRanges(%v)\n", list) + data := []CdlRange{} + + start := -1 + //end := -1 + prev := -1 + for _, addr := range list { + if start == -1 { + start = addr + } + + if prev != -1 && prev != addr-1 { + data = append(data, CdlRange{ + Start: fmt.Sprintf("0x%X", start), + End: fmt.Sprintf("0x%X", prev), + }) + + //fmt.Printf("start: 0x%X end: 0x%X\n", start, prev) + + start = addr + } + + prev = addr + } + + if start != -1 && prev != -1 { + data = append(data, CdlRange{ + Start: fmt.Sprintf("0x%X", start), + End: fmt.Sprintf("0x%X", prev), + }) + + //fmt.Println("start:", start, "end:", prev) + } + + return data +} + +func (cdl *CodeDataLog) WriteTo(w io.Writer) (int64, error) { + clean := &CodeDataLog{ + Code: []CdlRange{}, + Data: []CdlRange{}, + } + + keys := []int{} + for k, _ := range cdl.cache { + keys = append(keys, k) + } + + slices.Sort(keys) + + code := []int{} + data := []int{} + + for _, k := range keys { + b := cdl.cache[k] + if b & cdlCode == cdlCode { + code = append(code, k) + } + + if b & cdlData == cdlData { + data = append(data, k) + } + } + + clean.Code = getRanges(code) + clean.Data = getRanges(data) + + raw, err := json.MarshalIndent(clean, "", "\t") + if err != nil { + return 0, err + } + + n, err := w.Write(raw) + return int64(n), err +} + func (cdl *CodeDataLog) setData(scriptOffset int) { if cdl.cache == nil { err := cdl.doCache() diff --git a/script/parser.go b/script/parser.go index 8c13e8f..7ef55d2 100644 --- a/script/parser.go +++ b/script/parser.go @@ -45,8 +45,6 @@ func SmartParse(rawinput []byte, startAddr int, cdl *CodeDataLog) (*Script, erro } p := &Parser{ - // Don't use CDL that was passed in - cdl: &CodeDataLog{}, script: &Script{ Tokens: []*Token{}, @@ -54,12 +52,18 @@ func SmartParse(rawinput []byte, startAddr int, cdl *CodeDataLog) (*Script, erro StackAddress: (int(rawinput[1])<<8) | int(rawinput[0]), StartAddress: startAddr, Labels: make(map[int]*Label), // map[location]name + + CDL: cdl, }, rawinput: rawinput, startAddr: startAddr, } + if p.script.CDL == nil { + p.script.CDL = &CodeDataLog{} + } + tokenMap := make(map[int]*Token) // starting point is the third byte in the script. @@ -95,7 +99,7 @@ INNER: //fmt.Printf("{$%04X} %s\n", token.Offset, token.String(map[int]*Label{})) - p.cdl.setCode(p.current) + p.script.CDL.setCode(p.current) if raw < 0x80 { continue } @@ -181,21 +185,21 @@ func Parse(rawinput []byte, startAddr int, cdl *CodeDataLog) (*Script, error) { } p := &Parser{ - cdl: cdl, script: &Script{ Tokens: []*Token{}, Warnings: []string{}, StackAddress: (int(rawinput[1])<<8) | int(rawinput[0]), StartAddress: startAddr, Labels: make(map[int]*Label), // map[location]name + CDL: cdl, }, rawinput: rawinput, startAddr: startAddr, } tokenMap := make(map[int]*Token) - if p.cdl == nil { - p.cdl = &CodeDataLog{} + if p.script.CDL == nil { + p.script.CDL = &CodeDataLog{} } //earliestVar := len(p.rawinput)-2 @@ -217,8 +221,8 @@ func Parse(rawinput []byte, startAddr int, cdl *CodeDataLog) (*Script, error) { p.script.Tokens = append(p.script.Tokens, token) tokenMap[token.Offset] = token - if raw < 0x80 || p.cdl.IsData(p.current+startAddr) { // || p.current >= earliestVar { - if p.cdl.IsData(p.current+startAddr) { + if raw < 0x80 || p.script.CDL.IsData(p.current+startAddr) { // || p.current >= earliestVar { + if p.script.CDL.IsData(p.current+startAddr) { token.IsData = true //fmt.Print(".") //fmt.Printf("%#v\n", token) @@ -321,6 +325,7 @@ func (p *Parser) parseToken(token *Token, raw byte) error { switch op.OpCount { case -1: // null terminated for ; p.current < len(p.rawinput); p.current++ { + p.script.CDL.setCode(p.current) val := ByteVal(p.rawinput[p.current]) args = append(args, val) if p.rawinput[p.current] == 0x00 { @@ -332,6 +337,7 @@ func (p *Parser) parseToken(token *Token, raw byte) error { // FIXME: wtf makes this different from -3?? p.current++ l := int(p.rawinput[p.current]) + p.script.CDL.setCode(p.current) args = append(args, ByteVal(l)) p.current++ for c := 0; c < l; c++ { @@ -349,6 +355,7 @@ func (p *Parser) parseToken(token *Token, raw byte) error { p.current++ l := int(p.rawinput[p.current]) args = append(args, ByteVal(l)) + p.script.CDL.setCode(p.current) p.current++ for c := 0; c < l; c++ { args = append(args, WordVal([2]byte{p.rawinput[p.current], p.rawinput[p.current+1]})) @@ -358,7 +365,10 @@ func (p *Parser) parseToken(token *Token, raw byte) error { case 2: args = append(args, WordVal([2]byte{p.rawinput[p.current+1], p.rawinput[p.current+2]})) + p.script.CDL.setCode(p.current+1) + p.script.CDL.setCode(p.current+2) p.current+=2 + //fmt.Printf("var at $%04X\n", val.Int()) //if val.Int() > p.startAddr && val.Int() < p.startAddr+len(p.rawinput) && p.earliestVar > val.Int() { // fmt.Printf("new earliest: $%04X\n", val.Int()) @@ -367,6 +377,7 @@ func (p *Parser) parseToken(token *Token, raw byte) error { case 1: p.current++ + p.script.CDL.setCode(p.current) args = append(args, ByteVal(p.rawinput[p.current])) } diff --git a/script/script.go b/script/script.go index 07825f3..4fcf37d 100644 --- a/script/script.go +++ b/script/script.go @@ -11,6 +11,7 @@ type Script struct { StackAddress int Labels map[int]*Label + CDL *CodeDataLog } func (s *Script) Stats() Stats {