[script] Improve CDL logic

- CDL data can now be output to a file.  If --cdl-output isn't given,
  but --cdl is given, the input file is overwritten with the new data.
  If no CDL file is given no data is written.
- Count arguments as "Code"
- The SmartParse function no longer creates a new CDL.  It will use and
  update what it was given.
- The just-stats command does not write CDL data even though it
  generates it.

Variable length arguments are not properly handled yet.  Currently, just
the OP code and first argument (length) are set at Code.  The rest are
ignored.
This commit is contained in:
Zorchenhimer 2025-09-14 18:06:46 -04:00
parent 11cfad1e1a
commit bfc7beb382
Signed by: Zorchenhimer
GPG Key ID: 70A1AB767AAB9C20
4 changed files with 131 additions and 12 deletions

View File

@ -21,6 +21,7 @@ type Arguments struct {
StatsFile string `arg:"--stats" help:"file to write some statistics to"` StatsFile string `arg:"--stats" help:"file to write some statistics to"`
LabelFile string `arg:"--labels" help:"file containing address/label pairs"` LabelFile string `arg:"--labels" help:"file containing address/label pairs"`
CDL string `arg:"--cdl" help:"CodeDataLog json file"` CDL string `arg:"--cdl" help:"CodeDataLog json file"`
CDLOutput string `arg:"--cdl-output"`
Smart bool `arg:"--smart"` Smart bool `arg:"--smart"`
start int start int
@ -103,10 +104,6 @@ func run(args *Arguments) error {
return 0 return 0
}) })
//for _, lbl := range scr.Labels {
// fmt.Println(lbl)
//}
for _, token := range scr.Tokens { for _, token := range scr.Tokens {
fmt.Fprintln(outfile, token.String(scr.Labels)) 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 return nil
} }

View File

@ -6,6 +6,7 @@ import (
"encoding/json" "encoding/json"
"strconv" "strconv"
"fmt" "fmt"
"slices"
) )
type CodeDataLog struct { type CodeDataLog struct {
@ -28,8 +29,101 @@ var (
cdlUnknown cdlBit = 0x00 cdlUnknown cdlBit = 0x00
cdlCode cdlBit = 0x01 cdlCode cdlBit = 0x01
cdlData cdlBit = 0x02 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) { func (cdl *CodeDataLog) setData(scriptOffset int) {
if cdl.cache == nil { if cdl.cache == nil {
err := cdl.doCache() err := cdl.doCache()

View File

@ -45,8 +45,6 @@ func SmartParse(rawinput []byte, startAddr int, cdl *CodeDataLog) (*Script, erro
} }
p := &Parser{ p := &Parser{
// Don't use CDL that was passed in
cdl: &CodeDataLog{},
script: &Script{ script: &Script{
Tokens: []*Token{}, Tokens: []*Token{},
@ -54,12 +52,18 @@ func SmartParse(rawinput []byte, startAddr int, cdl *CodeDataLog) (*Script, erro
StackAddress: (int(rawinput[1])<<8) | int(rawinput[0]), StackAddress: (int(rawinput[1])<<8) | int(rawinput[0]),
StartAddress: startAddr, StartAddress: startAddr,
Labels: make(map[int]*Label), // map[location]name Labels: make(map[int]*Label), // map[location]name
CDL: cdl,
}, },
rawinput: rawinput, rawinput: rawinput,
startAddr: startAddr, startAddr: startAddr,
} }
if p.script.CDL == nil {
p.script.CDL = &CodeDataLog{}
}
tokenMap := make(map[int]*Token) tokenMap := make(map[int]*Token)
// starting point is the third byte in the script. // 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{})) //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 { if raw < 0x80 {
continue continue
} }
@ -181,21 +185,21 @@ func Parse(rawinput []byte, startAddr int, cdl *CodeDataLog) (*Script, error) {
} }
p := &Parser{ p := &Parser{
cdl: cdl,
script: &Script{ script: &Script{
Tokens: []*Token{}, Tokens: []*Token{},
Warnings: []string{}, Warnings: []string{},
StackAddress: (int(rawinput[1])<<8) | int(rawinput[0]), StackAddress: (int(rawinput[1])<<8) | int(rawinput[0]),
StartAddress: startAddr, StartAddress: startAddr,
Labels: make(map[int]*Label), // map[location]name Labels: make(map[int]*Label), // map[location]name
CDL: cdl,
}, },
rawinput: rawinput, rawinput: rawinput,
startAddr: startAddr, startAddr: startAddr,
} }
tokenMap := make(map[int]*Token) tokenMap := make(map[int]*Token)
if p.cdl == nil { if p.script.CDL == nil {
p.cdl = &CodeDataLog{} p.script.CDL = &CodeDataLog{}
} }
//earliestVar := len(p.rawinput)-2 //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) p.script.Tokens = append(p.script.Tokens, token)
tokenMap[token.Offset] = token tokenMap[token.Offset] = token
if raw < 0x80 || p.cdl.IsData(p.current+startAddr) { // || p.current >= earliestVar { if raw < 0x80 || p.script.CDL.IsData(p.current+startAddr) { // || p.current >= earliestVar {
if p.cdl.IsData(p.current+startAddr) { if p.script.CDL.IsData(p.current+startAddr) {
token.IsData = true token.IsData = true
//fmt.Print(".") //fmt.Print(".")
//fmt.Printf("%#v\n", token) //fmt.Printf("%#v\n", token)
@ -321,6 +325,7 @@ func (p *Parser) parseToken(token *Token, raw byte) error {
switch op.OpCount { switch op.OpCount {
case -1: // null terminated case -1: // null terminated
for ; p.current < len(p.rawinput); p.current++ { for ; p.current < len(p.rawinput); p.current++ {
p.script.CDL.setCode(p.current)
val := ByteVal(p.rawinput[p.current]) val := ByteVal(p.rawinput[p.current])
args = append(args, val) args = append(args, val)
if p.rawinput[p.current] == 0x00 { 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?? // FIXME: wtf makes this different from -3??
p.current++ p.current++
l := int(p.rawinput[p.current]) l := int(p.rawinput[p.current])
p.script.CDL.setCode(p.current)
args = append(args, ByteVal(l)) args = append(args, ByteVal(l))
p.current++ p.current++
for c := 0; c < l; c++ { for c := 0; c < l; c++ {
@ -349,6 +355,7 @@ func (p *Parser) parseToken(token *Token, raw byte) error {
p.current++ p.current++
l := int(p.rawinput[p.current]) l := int(p.rawinput[p.current])
args = append(args, ByteVal(l)) args = append(args, ByteVal(l))
p.script.CDL.setCode(p.current)
p.current++ p.current++
for c := 0; c < l; c++ { for c := 0; c < l; c++ {
args = append(args, WordVal([2]byte{p.rawinput[p.current], p.rawinput[p.current+1]})) 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: case 2:
args = append(args, WordVal([2]byte{p.rawinput[p.current+1], p.rawinput[p.current+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 p.current+=2
//fmt.Printf("var at $%04X\n", val.Int()) //fmt.Printf("var at $%04X\n", val.Int())
//if val.Int() > p.startAddr && val.Int() < p.startAddr+len(p.rawinput) && p.earliestVar > 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()) // fmt.Printf("new earliest: $%04X\n", val.Int())
@ -367,6 +377,7 @@ func (p *Parser) parseToken(token *Token, raw byte) error {
case 1: case 1:
p.current++ p.current++
p.script.CDL.setCode(p.current)
args = append(args, ByteVal(p.rawinput[p.current])) args = append(args, ByteVal(p.rawinput[p.current]))
} }

View File

@ -11,6 +11,7 @@ type Script struct {
StackAddress int StackAddress int
Labels map[int]*Label Labels map[int]*Label
CDL *CodeDataLog
} }
func (s *Script) Stats() Stats { func (s *Script) Stats() Stats {