Compare commits

..

No commits in common. "63de05e9dd48689dc0e2559c2e1ee7eaa750710a" and "bfc7beb38234667f2f69a9e415a053161232ce98" have entirely different histories.

7 changed files with 155 additions and 416 deletions

View File

@ -5,6 +5,7 @@ import (
"os"
"strings"
"strconv"
"bufio"
"slices"
"errors"
@ -22,7 +23,6 @@ type Arguments struct {
CDL string `arg:"--cdl" help:"CodeDataLog json file"`
CDLOutput string `arg:"--cdl-output"`
Smart bool `arg:"--smart"`
NoAddrPrefix bool `arg:"--no-addr-prefix"`
start int
}
@ -45,13 +45,10 @@ func run(args *Arguments) error {
var cdl *script.CodeDataLog
if args.CDL != "" {
//fmt.Println(" CDL:", args.CDL)
cdl, err = script.CdlFromJsonFile(args.CDL)
if err != nil {
if errors.Is(err, os.ErrNotExist) {
fmt.Println("WARN: CDL file doesn't exist")
} else {
return fmt.Errorf("CDL Parse error: %w", err)
}
//return fmt.Errorf("CDL Parse error: %w", err)
cdl = nil
}
}
@ -72,24 +69,14 @@ func run(args *Arguments) error {
}
if args.LabelFile != "" {
err = scr.LabelsFromJsonFile(args.LabelFile)
//labels, err := parseLabelFile(args.LabelFile)
labels, err := parseLabelFile(args.LabelFile)
if err != nil {
if errors.Is(err, os.ErrNotExist) {
fmt.Println("WARN: Label file doesn't exist")
} else {
return fmt.Errorf("Labels parse error: %w", err)
}
return fmt.Errorf("Labels parse error: %w", err)
}
err = scr.WriteLabelsToFile(args.LabelFile)
if err != nil {
return fmt.Errorf("Labels write error: %w", err)
for _, label := range labels {
scr.Labels[label.Address] = label
}
//for _, label := range labels {
// scr.Labels[label.Address] = label
//}
}
outfile := os.Stdout
@ -118,7 +105,7 @@ func run(args *Arguments) error {
})
for _, token := range scr.Tokens {
fmt.Fprintln(outfile, token.String(scr.Labels, args.NoAddrPrefix))
fmt.Fprintln(outfile, token.String(scr.Labels))
}
if args.StatsFile != "" {
@ -148,16 +135,67 @@ func run(args *Arguments) error {
if err != nil {
return fmt.Errorf("Error writing CDL file: %w", err)
}
err = scr.DebugCDL(cdlout+".dbg")
if err != nil {
return fmt.Errorf("Error writing CDL debug file: %w", err)
}
}
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)

View File

@ -13,10 +13,8 @@ type CodeDataLog struct {
Code []CdlRange
Data []CdlRange
EntryPoints []string
entries []int
cache map[int]cdlBit
offset int
}
type CdlRange struct {
@ -34,26 +32,6 @@ var (
//cdlOpCode cdlBit = 0x04
)
func (c cdlBit) String() string {
switch c {
case cdlUnknown:
return "UNKN"
case cdlCode:
return "CODE"
case cdlData:
return "DATA"
default:
return "????"
}
}
func NewCDL() *CodeDataLog {
return &CodeDataLog{
entries: []int{},
cache: make(map[int]cdlBit),
}
}
func (cdl *CodeDataLog) WriteToFile(filename string) error {
file, err := os.Create(filename)
if err != nil {
@ -69,10 +47,6 @@ func (cdl *CodeDataLog) WriteToFile(filename string) error {
return werr
}
func (cdl *CodeDataLog) getEntries() []int {
return cdl.entries
}
func getRanges(list []int) []CdlRange {
//fmt.Printf("getRanges(%v)\n", list)
data := []CdlRange{}
@ -128,10 +102,6 @@ func (cdl *CodeDataLog) WriteTo(w io.Writer) (int64, error) {
data := []int{}
for _, k := range keys {
if k < 0x6000 {
continue
}
b := cdl.cache[k]
if b & cdlCode == cdlCode {
code = append(code, k)
@ -145,10 +115,6 @@ func (cdl *CodeDataLog) WriteTo(w io.Writer) (int64, error) {
clean.Code = getRanges(code)
clean.Data = getRanges(data)
for _, ent := range cdl.entries {
clean.EntryPoints = append(clean.EntryPoints, fmt.Sprintf("0x%X", ent))
}
raw, err := json.MarshalIndent(clean, "", "\t")
if err != nil {
return 0, err
@ -158,12 +124,26 @@ func (cdl *CodeDataLog) WriteTo(w io.Writer) (int64, error) {
return int64(n), err
}
func (cdl *CodeDataLog) setData(addr int) {
cdl.cache[addr] |= cdlData
func (cdl *CodeDataLog) setData(scriptOffset int) {
if cdl.cache == nil {
err := cdl.doCache()
if err != nil {
panic(fmt.Sprintf("CDL data error: %w", err))
}
}
cdl.cache[scriptOffset+cdl.offset] |= cdlData
}
func (cdl *CodeDataLog) setCode(addr int) {
cdl.cache[addr] |= cdlCode
func (cdl *CodeDataLog) setCode(scriptOffset int) {
if cdl.cache == nil {
err := cdl.doCache()
if err != nil {
panic(fmt.Sprintf("CDL data error: %w", err))
}
}
cdl.cache[scriptOffset+cdl.offset] |= cdlCode
}
func (cdl *CodeDataLog) doCache() error {
@ -181,6 +161,10 @@ func (cdl *CodeDataLog) doCache() error {
}
for i := int(start); i <= int(end); i++ {
if _, ok := cdl.cache[i]; !ok {
cdl.cache[i] = cdlUnknown
}
cdl.cache[i] |= cdlCode
}
}
@ -197,34 +181,25 @@ func (cdl *CodeDataLog) doCache() error {
}
for i := int(start); i <= int(end); i++ {
if _, ok := cdl.cache[i]; !ok {
cdl.cache[i] = cdlUnknown
}
cdl.cache[i] |= cdlData
}
}
cdl.entries = []int{}
for _, ent := range cdl.EntryPoints {
addr, err := strconv.ParseInt(ent, 0, 32)
if err != nil {
return fmt.Errorf("Invalid entry point: %q", ent)
}
cdl.entries = append(cdl.entries, int(addr))
}
return nil
}
func CdlFromJson(r io.Reader) (*CodeDataLog, error) {
cdl := NewCDL()
cdl := &CodeDataLog{}
dec := json.NewDecoder(r)
err := dec.Decode(cdl)
if err != nil {
return nil, err
}
//cdl.Data = []CdlRange{}
cdl.doCache()
return cdl, nil
}
@ -238,6 +213,13 @@ func CdlFromJsonFile(filename string) (*CodeDataLog, error) {
}
func (cdl *CodeDataLog) IsData(addr int) bool {
if cdl.cache == nil {
err := cdl.doCache()
if err != nil {
panic(fmt.Sprintf("CDL data error: %w", err))
}
}
val, ok := cdl.cache[addr]
if !ok {
return false
@ -247,6 +229,13 @@ func (cdl *CodeDataLog) IsData(addr int) bool {
}
func (cdl *CodeDataLog) IsCode(addr int) bool {
if cdl.cache == nil {
err := cdl.doCache()
if err != nil {
panic(fmt.Sprintf("CDL data error: %w", err))
}
}
val, ok := cdl.cache[addr]
if !ok {
return false

View File

@ -30,12 +30,7 @@ var Instructions []*Instruction = []*Instruction{
&Instruction{ 0x87, 0, 0, 0, false, "loop"},
&Instruction{ 0x88, 0, 0, 0, false, "play_sound"},
// ArgA: Foreground color index
// ArgB: Background color index
// ArgC: Ignored??
&Instruction{ 0x89, 3, 0, 0, false, "draw_string"},
&Instruction{ 0x89, 3, 0, 0, false, ""},
&Instruction{ 0x8A, 0, 2, 0, false, "pop_string_to_addr"},
&Instruction{ 0x8B, 1, 0, 0, false, ""},
&Instruction{ 0x8C, 0, 0, 1, false, "string_length"},
@ -88,48 +83,30 @@ var Instructions []*Instruction = []*Instruction{
&Instruction{ 0xA8, 5, 0, 0, false, ""},
&Instruction{ 0xA9, 1, 0, 0, false, ""},
&Instruction{ 0xAA, 1, 0, 0, false, "long_jump"},
&Instruction{ 0xAA, 1, 0, 0, false, ""},
&Instruction{ 0xAB, 1, 0, 0, false, "long_call"},
&Instruction{ 0xAC, 0, 0, 0, false, "long_return"},
&Instruction{ 0xAD, 1, 0, 1, false, "absolute"},
&Instruction{ 0xAE, 1, 0, 1, false, "compare"},
&Instruction{ 0xAF, 0, 0, 1, false, "string_to_arg_a"},
&Instruction{ 0xAF, 0, 0, 1, false, ""},
&Instruction{ 0xB0, 1, 0, 16, false, "arg_a_to_string"},
&Instruction{ 0xB0, 1, 0, 16, false, ""},
&Instruction{ 0xB1, 1, 0, 16, false, "to_hex_string"},
&Instruction{ 0xB2, 0, 0, 1, false, ""},
&Instruction{ 0xB3, 7, 0, 0, false, ""}, // possible 16-bit inline?
// If ($471A) is > #$60, copy to ($4E). Setup for some other bullshit?
&Instruction{ 0xB4, 0, 0, 0, false, "indirect_copy_471A_4E"},
// Uses value at $471A as the source pointer (after copied into ArgumentA)
// and $4E as the destination pointer to copy a null-terminated string.
// Will break if the string is more than 256 bytes long (incl NULL byte).
// The value at $471A will be incremented by the number of bytes copied.
&Instruction{ 0xB5, 0, 0, 0, false, "string_copy"},
// find a better name for this one.
&Instruction{ 0xB6, 0, 0, 0, false, "word4E_to_word471A"},
&Instruction{ 0xB4, 0, 0, 0, false, ""},
&Instruction{ 0xB5, 0, 0, 0, false, ""},
&Instruction{ 0xB6, 0, 0, 0, false, ""},
// Uses the inline word as a pointer, and pushes the byte value at that
// address to the stack.
&Instruction{ 0xB7, 0, 2, 0, false, "push_var"},
&Instruction{ 0xB7, 0, 2, 0, false, "deref_ptr_inline"},
// Pushes the inline word to the stack
&Instruction{ 0xB8, 0, 2, 0, true, "push_word"},
// Pushes value at (inline address + word offset in stack)
&Instruction{ 0xB9, 0, 2, 0, false, "push_var_indexed"},
// Pushes data using inline value as pointer. Always reads 32 bytes at the
// address given.
&Instruction{ 0xBA, 0, 2, 0, false, "push_data_indirect"},
// Pushes inline null terminated data to the stack. Max of 32 bytes.
// Increments the stack pointer by 32 *always*, regardless of data size.
&Instruction{ 0xB9, 0, 2, 0, false, "push_word_indexed"},
&Instruction{ 0xBA, 0, 2, 0, false, "push"},
&Instruction{ 0xBB, 0, -1, 0, false, "push_data"},
&Instruction{ 0xBC, 0, 2, 0, false, "push_string_from_table"},
// Pops a byte off the stack and stores it at the inline address.
@ -170,12 +147,8 @@ var Instructions []*Instruction = []*Instruction{
&Instruction{ 0xD6, 1, 0, 16, false, "truncate_string"},
&Instruction{ 0xD7, 1, 0, 16, false, "trim_string"},
// ArgA is number of bytes to trim.
// ArgB is length of string. 0xD8 sets this to 32.
&Instruction{ 0xD8, 1, 0, 16, false, "trim_string_start_32"},
&Instruction{ 0xD8, 1, 0, 16, false, "trim_string_start"},
&Instruction{ 0xD9, 2, 0, 16, false, "trim_string_start"},
&Instruction{ 0xDA, 1, 0, 16, false, "to_int_string"},
&Instruction{ 0xDB, 3, 0, 0, false, ""},
&Instruction{ 0xDC, 5, 0, 0, false, ""},
@ -208,7 +181,7 @@ var Instructions []*Instruction = []*Instruction{
&Instruction{ 0xE7, 7, 0, 0, false, "draw_metasprite"},
&Instruction{ 0xE8, 1, 0, 0, false, "setup_tape_nmi"},
&Instruction{ 0xE9, 0, 1, 0, false, "setup_loop"},
&Instruction{ 0xEA, 0, 2, 0, false, "string_write_to_table"},
&Instruction{ 0xEA, 0, 0, 0, false, "string_write_to_table"},
// Reads and saves tiles from the PPU, then draws over them.
// This is used to draw dialog boxes, so saving what it overwrites
@ -221,15 +194,7 @@ var Instructions []*Instruction = []*Instruction{
&Instruction{ 0xED, 1, 0, 0, false, "disable_sprites"},
&Instruction{ 0xEE, 1, -3, 0, false, "call_switch"},
// Draw string as sprites
// ArgA: Palette ID
// ArgB: FG palette index
// ArgC: BG palette index
// ArgD: Priority (something else too?)
// ArgE: X coord
// ArgF: Y coord
&Instruction{ 0xEF, 6, 0, 0, false, "draw_string_sprites"},
&Instruction{ 0xEF, 6, 0, 0, false, ""},
&Instruction{ 0xF0, 0, 0, 0, false, "disable_sprites"},
&Instruction{ 0xF1, 4, 0, 0, false, ""},

View File

@ -2,10 +2,6 @@ package script
import (
"fmt"
"io"
"os"
"encoding/json"
"strconv"
)
type Label struct {
@ -15,36 +11,6 @@ type Label struct {
FarLabel bool
}
type JsonLabel struct {
Address string
Name string
Comment string
FarLabel bool
}
func (l Label) JsonLabel() JsonLabel {
return JsonLabel{
Address: fmt.Sprintf("0x%X", l.Address),
Name: l.Name,
Comment: l.Comment,
FarLabel: l.FarLabel,
}
}
func (l JsonLabel) Label() (*Label, error) {
addr, err := strconv.ParseInt(l.Address, 0, 32)
if err != nil {
return nil, fmt.Errorf("Invalid address: %q", l.Address)
}
return &Label{
Address: int(addr),
Name: l.Name,
Comment: l.Comment,
FarLabel: l.FarLabel,
}, nil
}
func AutoLabel(address int) *Label {
return &Label{
Address: address,
@ -74,61 +40,3 @@ func NewLabel(address int, name string) *Label {
}
}
func (s *Script) LabelsFromJsonFile(filename string) error {
file, err := os.Open(filename)
if err != nil {
return err
}
defer file.Close()
return s.LabelsFromJson(file)
}
func (s *Script) LabelsFromJson(r io.Reader) error {
lbls := []JsonLabel{}
dec := json.NewDecoder(r)
err := dec.Decode(&lbls)
if err != nil {
return err
}
if s.Labels == nil {
s.Labels = make(map[int]*Label)
}
for _, lbl := range lbls {
l, err := lbl.Label()
if err != nil {
return err
}
s.Labels[l.Address] = l
}
return nil
}
func (s *Script) WriteLabelsToFile(filename string) error {
file, err := os.Create(filename)
if err != nil {
return err
}
defer file.Close()
return s.WriteLabels(file)
}
func (s *Script) WriteLabels(w io.Writer) error {
slice := []JsonLabel{}
for _, lbl := range s.Labels {
slice = append(slice, lbl.JsonLabel())
}
raw, err := json.MarshalIndent(slice, "", "\t")
if err != nil {
return err
}
_, err = w.Write(raw)
return err
}

View File

@ -54,7 +54,6 @@ func SmartParse(rawinput []byte, startAddr int, cdl *CodeDataLog) (*Script, erro
Labels: make(map[int]*Label), // map[location]name
CDL: cdl,
origSize: len(rawinput),
},
rawinput: rawinput,
@ -62,28 +61,17 @@ func SmartParse(rawinput []byte, startAddr int, cdl *CodeDataLog) (*Script, erro
}
if p.script.CDL == nil {
p.script.CDL = NewCDL()
p.script.CDL = &CodeDataLog{}
}
tokenMap := make(map[int]*Token)
// starting point is the third byte in the script.
branches := []int{ 2 }
for _, ent := range p.script.CDL.getEntries() {
addr := ent-startAddr
if addr > 0 {
branches = append(branches, addr)
}
}
visited := make([]bool, len(p.rawinput))
for len(branches) > 0 {
st := branches[0]+startAddr
//fmt.Printf("start @ $%04X\n", st)
p.script.Labels[st] = AutoLabel(st)
//fmt.Printf("start @ $%04X\n", branches[0]+startAddr)
INNER:
for p.current = branches[0]; p.current < len(p.rawinput); p.current++ {
//branches = branches[1:]
@ -111,7 +99,7 @@ INNER:
//fmt.Printf("{$%04X} %s\n", token.Offset, token.String(map[int]*Label{}))
p.script.CDL.setCode(p.current+p.startAddr)
p.script.CDL.setCode(p.current)
if raw < 0x80 {
continue
}
@ -124,7 +112,7 @@ INNER:
//fmt.Println(token.String(map[int]*Label{}))
switch raw {
case 0x86, 0xAC, 0xAA, 0xFF, 0x81, 0x9B, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7, 0xF8, 0xFD: // return, long_return, long_jump, break_engine & halts
case 0x86, 0xAC, 0xFF, 0x81, 0x9B, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7, 0xF8, 0xFD: // return, long_return, break_engine & halts
//fmt.Printf("[$%04X] %s\n",
// token.Offset, token.Instruction.Name)
break INNER
@ -174,13 +162,11 @@ INNER:
}
}
if token.Instruction.OpCount == 2 && !token.Instruction.InlineImmediate {
if token.Instruction.OpCount == 2 {
val := token.Inline[0].Int()
if _, ok := p.script.Labels[val]; !ok {//&& val >= startAddr {
if _, ok := p.script.Labels[val]; !ok {
p.script.Labels[val] = AutoLabelVar(val)
}
p.script.CDL.setData(val)
p.script.CDL.setData(val+1)
}
}
@ -190,40 +176,6 @@ INNER:
branches = branches[1:]
}
// Add data tokens
for addr, bit := range p.script.CDL.cache {
if addr < 0x6002 {
continue
}
// ignore code bytes
if bit & cdlCode == cdlCode {
continue
}
// ignore labels outside the script's address range
if addr > len(rawinput)+0x6000 {
continue
}
if _, ok := p.script.Labels[addr]; ok {
p.script.Tokens = append(p.script.Tokens, &Token{
Offset: addr,
Inline: []InlineVal{NewWordVal([]byte{rawinput[addr-0x6000], rawinput[addr+1-0x6000]})},
IsVariable: true,
IsData: true,
cdl: bit.String(),
})
} else {
p.script.Tokens = append(p.script.Tokens, &Token{
Offset: addr,
Raw: rawinput[addr-0x6000],
IsData: true,
cdl: bit.String(),
})
}
}
return p.script, nil
}
@ -240,7 +192,6 @@ func Parse(rawinput []byte, startAddr int, cdl *CodeDataLog) (*Script, error) {
StartAddress: startAddr,
Labels: make(map[int]*Label), // map[location]name
CDL: cdl,
origSize: len(rawinput),
},
rawinput: rawinput,
startAddr: startAddr,
@ -248,7 +199,7 @@ func Parse(rawinput []byte, startAddr int, cdl *CodeDataLog) (*Script, error) {
tokenMap := make(map[int]*Token)
if p.script.CDL == nil {
p.script.CDL = NewCDL()
p.script.CDL = &CodeDataLog{}
}
//earliestVar := len(p.rawinput)-2
@ -351,8 +302,8 @@ func Parse(rawinput []byte, startAddr int, cdl *CodeDataLog) (*Script, error) {
if t.Instruction.OpCount == 2 && !t.Instruction.InlineImmediate {
addr := t.Inline[0].Int()
if _, ok := tokenMap[addr]; ok {
//tok.IsVariable = true
if tok, ok := tokenMap[addr]; ok {
tok.IsVariable = true
p.script.Labels[addr] = AutoLabelVar(addr) //fmt.Sprintf("Var_%04X", addr)
}
}
@ -374,7 +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+p.startAddr)
p.script.CDL.setCode(p.current)
val := ByteVal(p.rawinput[p.current])
args = append(args, val)
if p.rawinput[p.current] == 0x00 {
@ -385,12 +336,10 @@ func (p *Parser) parseToken(token *Token, raw byte) error {
case -2: // count then count words
// FIXME: wtf makes this different from -3??
p.current++
l := int(p.rawinput[p.current])
p.script.CDL.setCode(p.current+p.startAddr)
p.script.CDL.setCode(p.current)
args = append(args, ByteVal(l))
p.current++
for c := 0; c < l; c++ {
if len(p.rawinput) <= p.current+1 {
return errors.Join(ErrEarlyEOF,
@ -398,37 +347,26 @@ func (p *Parser) parseToken(token *Token, raw byte) error {
}
args = append(args, WordVal([2]byte{p.rawinput[p.current], p.rawinput[p.current+1]}))
p.script.CDL.setCode(p.current+p.startAddr)
p.script.CDL.setCode(p.current+p.startAddr+1)
p.current+=2
}
p.current--
case -3: // count then count words. "default" is no call (skip Code_Pointer to after args)
p.current++
l := int(p.rawinput[p.current])
args = append(args, ByteVal(l))
p.script.CDL.setCode(p.current+p.startAddr)
p.script.CDL.setCode(p.current)
p.current++
for c := 0; c < l; c++ {
if len(p.rawinput) <= p.current+1 {
return errors.Join(ErrEarlyEOF,
fmt.Errorf("OP early end at offset 0x%X (%d) {%d} %#v", p.current, p.current, l, op))
}
args = append(args, WordVal([2]byte{p.rawinput[p.current], p.rawinput[p.current+1]}))
p.script.CDL.setCode(p.current+p.startAddr)
p.script.CDL.setCode(p.current+p.startAddr+1)
p.current+=2
}
p.current--
case 2:
args = append(args, WordVal([2]byte{p.rawinput[p.current+1], p.rawinput[p.current+2]}))
p.script.CDL.setCode(p.current+p.startAddr+1)
p.script.CDL.setCode(p.current+p.startAddr+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())
@ -439,7 +377,7 @@ func (p *Parser) parseToken(token *Token, raw byte) error {
case 1:
p.current++
p.script.CDL.setCode(p.current+p.startAddr)
p.script.CDL.setCode(p.current)
args = append(args, ByteVal(p.rawinput[p.current]))
}

View File

@ -1,8 +1,6 @@
package script
import (
"fmt"
"os"
)
type Script struct {
@ -14,8 +12,6 @@ type Script struct {
Labels map[int]*Label
CDL *CodeDataLog
origSize int // size of the binary input
}
func (s *Script) Stats() Stats {
@ -38,30 +34,3 @@ func (s *Script) Stats() Stats {
return st
}
func (s *Script) DebugCDL(filename string) error {
if s.origSize == 0 {
return fmt.Errorf("origSize == 0")
}
if s.CDL.cache == nil {
err := s.CDL.doCache()
if err != nil {
return fmt.Errorf("doCache() error: %w", err)
}
}
dat := make([]byte, s.origSize)
for i := 2; i < len(dat); i++ {
if val, ok := s.CDL.cache[i+0x6000]; ok {
dat[i] = byte(val)
}
}
err := os.WriteFile(filename, dat, 0644)
if err != nil {
return fmt.Errorf("WriteFile() error: %w", err)
}
return nil
}

View File

@ -13,23 +13,16 @@ type Token struct {
IsVariable bool // target of something else
IsData bool // from CDL
cdl string // CDL string type
Instruction *Instruction
}
func (t Token) String(labels map[int]*Label, suppAddr bool) string {
func (t Token) String(labels map[int]*Label) string {
suffix := ""
switch t.Raw {
case 0x86, 0xAC, 0xAA: // Newline after return, long_return, & long_jump
case 0x86: // Newline after return
suffix = "\n"
}
offset := ""
if !suppAddr {
offset = fmt.Sprintf("[%04X] ", t.Offset)
}
prefix := ""
if lbl, ok := labels[t.Offset]; ok {
comment := ""
@ -43,44 +36,21 @@ func (t Token) String(labels map[int]*Label, suppAddr bool) string {
prefix = "\n"+comment+name
}
if t.IsVariable {
return fmt.Sprintf("%s%s%02X %-5s : %d %s%s",
if t.Instruction == nil {
return fmt.Sprintf("%s[%04X] %02X %-5s : %d%s",
prefix,
offset,
t.Offset,
t.Raw,
"",
t.Inline[0].Int(),
t.Inline[0].HexString(),
int(t.Raw),
suffix,
)
}
if t.Instruction == nil {
if t.IsData == false {
return fmt.Sprintf("%s%s%02X %-5s : %d%s",
prefix,
offset,
t.Raw,
"",
int(t.Raw),
suffix,
)
} else if t.IsData {
return fmt.Sprintf("%s%s%02X %-5s : %d%s",
prefix,
offset,
t.Raw,
t.cdl,
int(t.Raw),
suffix,
)
}
}
if len(t.Inline) == 0 {
return fmt.Sprintf("%s%s%02X %-5s : %s%s",
return fmt.Sprintf("%s[%04X] %02X %-5s : %s%s",
prefix,
offset,
t.Offset,
t.Raw,
"",
t.Instruction.String(),
@ -90,7 +60,7 @@ func (t Token) String(labels map[int]*Label, suppAddr bool) string {
argstr := []string{}
for _, a := range t.Inline {
if lbl, ok := labels[a.Int()]; ok && !t.Instruction.InlineImmediate {
if lbl, ok := labels[a.Int()]; ok {
argstr = append(argstr, lbl.Name)
} else {
argstr = append(argstr, a.HexString())
@ -110,56 +80,18 @@ func (t Token) String(labels map[int]*Label, suppAddr bool) string {
switch t.Raw {
case 0xBB: // push_data
raw := []byte{}
ascii := true
for _, val := range t.Inline[1:len(t.Inline)-1] {
for _, b := range val.Bytes() {
raw = append(raw, b)
if b < 0x20 || b > 0x7E {
ascii = false
}
}
bs := []byte{}
for _, val := range t.Inline {
bs = append(bs, val.Bytes()...)
}
bs := ""
if ascii {
bs = fmt.Sprintf("%q", string(raw))
} else {
vals := []string{}
for _, b := range raw {
if b >= 0x20 && b <= 0x7E {
vals = append(vals, fmt.Sprintf("0x%02X{%c}", b, b))
} else {
vals = append(vals, fmt.Sprintf("0x%02X", b))
}
}
bs = "["+strings.Join(vals, " ")+"]"
}
//for _, val := range t.Inline {
// //bs = append(bs, val.Bytes()...)
// for _, b := range val.Bytes() {
// // These strings are strictly binary or ascii. If there's
// // non-ascii, don't try and read it as unicode if we find
// // some "valid" code points. Eg, 0xD?, 0xB? (%110?_????, %10??_????)
// if b < 0x20 || b > 0x7E {
// bs = append(bs, fmt.Sprintf("\\x%02x", b))
// } else {
// bs = append(bs, string(b))
// }
// }
//}
return fmt.Sprintf("%s%s%02X (...) : %s %s%s",
return fmt.Sprintf("%s[%04X] %02X (...) : %s %q%s",
prefix,
offset,
t.Offset,
t.Raw,
t.Instruction.String(),
//string(bs[1:len(bs)-1]),
//strings.Join(bs[1:len(bs)-1], ""),
string(bs[1:len(bs)-1]),
//strings.Join(argstr[1:], " "),
bs,
suffix,
)
@ -167,9 +99,9 @@ func (t Token) String(labels map[int]*Label, suppAddr bool) string {
case 0xC1, 0xEE: // switches
return fmt.Sprintf("%s%s%02X %-5s : %s %s%s",
return fmt.Sprintf("%s[%04X] %02X %-5s : %s %s%s",
prefix,
offset,
t.Offset,
t.Raw,
"",
t.Instruction.String(),
@ -178,9 +110,9 @@ func (t Token) String(labels map[int]*Label, suppAddr bool) string {
)
default:
return fmt.Sprintf("%s%s%02X %-5s : %s %s%s",
return fmt.Sprintf("%s[%04X] %02X %-5s : %s %s%s",
prefix,
offset,
t.Offset,
t.Raw,
strings.Join(bytestr, " "),
t.Instruction.String(),
@ -190,9 +122,9 @@ func (t Token) String(labels map[int]*Label, suppAddr bool) string {
}
return fmt.Sprintf("%s%s%s %s%s",
return fmt.Sprintf("%s%04X: %s %s%s",
prefix,
offset,
t.Offset,
t.Instruction.String(),
strings.Join(argstr, " "),
suffix,