diff --git a/Makefile b/Makefile index 59d485c..a4a994c 100644 --- a/Makefile +++ b/Makefile @@ -1,8 +1,9 @@ .PHONY: all -COMMANDS: bin/script-decode +all: bin/script-decode bin/sbutil -all: $(COMMANDS) - -bin/%: cmd/%.go script/*.go +bin/script-decode: cmd/script-decode.go script/*.go + go build -o $@ $< + +bin/sbutil: cmd/sbutil.go rom/*.go go build -o $@ $< diff --git a/cmd/script-decode.go b/cmd/script-decode.go index 6edd828..04bde2d 100644 --- a/cmd/script-decode.go +++ b/cmd/script-decode.go @@ -58,7 +58,7 @@ func run(args *Arguments) error { fmt.Fprintf(outfile, "; Stack address: $%04X\n\n", scr.StackAddress) for _, token := range scr.Tokens { - fmt.Fprintln(outfile, token) + fmt.Fprintln(outfile, token.String(scr.Labels)) } return nil diff --git a/script/instructions.go b/script/instructions.go index bc494a3..0329843 100644 --- a/script/instructions.go +++ b/script/instructions.go @@ -52,6 +52,8 @@ var Instructions []*Instruction = []*Instruction{ &Instruction{ 0x9B, 0, 0, 0, "halt"}, &Instruction{ 0x9C, 0, 0, 0, "toggle_44FE"}, &Instruction{ 0x9D, 2, 0, 0, "something_tape"}, + + // Calls 0xEB draw_overlay. Seems to draw a whole screen. &Instruction{ 0x9E, 2, 0, 0, ""}, &Instruction{ 0x9F, 6, 0, 0, ""}, @@ -135,7 +137,14 @@ var Instructions []*Instruction = []*Instruction{ &Instruction{ 0xDA, 1, 0, 16, "to_int_string"}, &Instruction{ 0xDB, 3, 0, 0, ""}, &Instruction{ 0xDC, 5, 0, 0, ""}, - &Instruction{ 0xDD, 5, 0, 0, ""}, + + // ArgA, ArgB: X,Y of corner A + // ArgC, ArgD: X,Y of corner B + // ArgE: fill value. This is an index into + // the table at $B451. + // Fills a box with a tile + &Instruction{ 0xDD, 5, 0, 0, "fill_box"}, + &Instruction{ 0xDE, 3, 0, 0, ""}, &Instruction{ 0xDF, 3, 0, 0, ""}, @@ -153,7 +162,14 @@ var Instructions []*Instruction = []*Instruction{ &Instruction{ 0xE8, 1, 0, 0, "setup_tape_nmi"}, &Instruction{ 0xE9, 0, 1, 0, "setup_loop"}, &Instruction{ 0xEA, 0, 0, 0, "string_write_to_table"}, - &Instruction{ 0xEB, 4, 0, 0, ""}, + + // Reads and saves tiles from the PPU, then draws over them. + // This is used to draw dialog boxes, so saving what it overwrites + // so it can re-draw them later makes sense. + // Not sure what the arguments actually mean. + // ArgB and ArgC are probably coordinates. + &Instruction{ 0xEB, 4, 0, 0, "draw_overlay"}, + &Instruction{ 0xEC, 2, 0, 0, "scroll"}, &Instruction{ 0xED, 1, 0, 0, "disable_sprites"}, &Instruction{ 0xEE, 1, -3, 0, "call_switch"}, diff --git a/script/parser.go b/script/parser.go index 3a9e1a9..c223dc6 100644 --- a/script/parser.go +++ b/script/parser.go @@ -24,7 +24,9 @@ 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 } + tokenMap := make(map[int]*Token) for i := 2; i < len(rawinput); i++ { raw := rawinput[i] @@ -35,6 +37,7 @@ func Parse(rawinput []byte, startAddr int) (*Script, error) { Inline: []InlineVal{}, } script.Tokens = append(script.Tokens, token) + tokenMap[token.Offset] = token if raw < 0x80 { continue @@ -102,6 +105,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) break } } @@ -122,6 +126,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) break } } @@ -130,6 +135,19 @@ func Parse(rawinput []byte, startAddr int) (*Script, error) { script.Warnings = append(script.Warnings, fmt.Sprintf("Warning: no target found for jump/call switch at offset $%04X; value: $%04X", t.Offset, addr)) } } + + default: + // if word arg, see if it's something in this script + if t.Instruction == nil { + continue + } + if t.Instruction.OpCount == 2 { + addr := t.Inline[0].Int() + if tok, ok := tokenMap[addr]; ok { + tok.IsVariable = true + script.Labels[addr] = fmt.Sprintf("Var_%04X", addr) + } + } } } diff --git a/script/script.go b/script/script.go index 81183df..ae8a2dc 100644 --- a/script/script.go +++ b/script/script.go @@ -9,4 +9,6 @@ type Script struct { StartAddress int StackAddress int + + Labels map[int]string } diff --git a/script/tokens.go b/script/tokens.go index 1db8704..56a5d9b 100644 --- a/script/tokens.go +++ b/script/tokens.go @@ -9,12 +9,13 @@ type Token struct { Offset int Raw byte Inline []InlineVal - IsTarget bool // target of a call/jump? + IsTarget bool // target of a call/jump? + IsVariable bool // target of something else Instruction *Instruction } -func (t Token) String() string { +func (t Token) String(labels map[int]string) string { suffix := "" switch t.Raw { case 0x86: @@ -22,8 +23,12 @@ func (t Token) String() string { } prefix := "" - if t.IsTarget { - prefix = fmt.Sprintf("\nL%04X:\n", t.Offset) + if t.IsTarget || t.IsVariable { + if lbl, ok := labels[t.Offset]; ok { + prefix = "\n"+lbl+":\n" + } else { + prefix = fmt.Sprintf("\nL%04X:\n", t.Offset) + } } if t.Raw < 0x80 { @@ -50,18 +55,26 @@ func (t Token) String() string { argstr := []string{} for _, a := range t.Inline { - argstr = append(argstr, a.HexString()) + if lbl, ok := labels[a.Int()]; ok { + argstr = append(argstr, lbl) + } else { + argstr = append(argstr, a.HexString()) + } } bytestr := []string{} for _, a := range t.Inline { for _, b := range a.Bytes() { - bytestr = append(bytestr, fmt.Sprintf("%02X", b)) + //if lbl, ok := labels[a.Int()]; ok { + // bytestr = append(bytestr, lbl) + //} else { + bytestr = append(bytestr, fmt.Sprintf("%02X", b)) + //} } } switch t.Raw { - case 0xBB: + case 0xBB: // push_data bs := []byte{} for _, val := range t.Inline { bs = append(bs, val.Bytes()...)