forked from mefistotelis/psx_mnd_sym
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
0 parents
commit 9ca85fc
Showing
6 changed files
with
275 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
*.sym |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
package main | ||
|
||
import ( | ||
"flag" | ||
"fmt" | ||
"log" | ||
|
||
"github.com/sanctuary/sym" | ||
) | ||
|
||
func main() { | ||
flag.Parse() | ||
for _, path := range flag.Args() { | ||
f, err := sym.ParseFile(path) | ||
fmt.Println(f) | ||
if err != nil { | ||
log.Fatalf("%+v", err) | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
package sym | ||
|
||
//go:generate stringer -linecomment -type Kind | ||
|
||
// Kind specifies the kind of a symbol. | ||
type Kind uint8 | ||
|
||
// Symbol kinds. | ||
const ( | ||
KindOverlay Kind = 0x98 // overlay | ||
) |
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,112 @@ | ||
// Package sym provides access to Playstation 1 symbol files (*.SYM). | ||
package sym | ||
|
||
import ( | ||
"bufio" | ||
"bytes" | ||
"encoding/binary" | ||
"fmt" | ||
"io" | ||
"os" | ||
"strings" | ||
|
||
"github.com/lunixbochs/struc" | ||
"github.com/pkg/errors" | ||
) | ||
|
||
// A File is PS1 symbol file. | ||
type File struct { | ||
// File header. | ||
Hdr *FileHeader | ||
// Symbols. | ||
Syms []*Symbol | ||
} | ||
|
||
// String returns the string representation of the symbol file. | ||
func (f *File) String() string { | ||
buf := &strings.Builder{} | ||
offset := 0 | ||
buf.WriteString(f.Hdr.String()) | ||
offset += binary.Size(*f.Hdr) | ||
for _, sym := range f.Syms { | ||
fmt.Fprintf(buf, "%06x: %s\n", offset, sym) | ||
offset += sym.Size() | ||
} | ||
return buf.String() | ||
} | ||
|
||
// A FileHeader is a PS1 symbol file header. | ||
type FileHeader struct { | ||
// File signature; MND. | ||
Signature [3]byte `struc:"[3]byte"` | ||
// File format version. | ||
Version uint8 `struc:"uint8,little"` | ||
// Target unit. | ||
TargetUnit uint32 `struc:"uint32,little"` | ||
} | ||
|
||
// String returns the string representation of the symbol file header. | ||
func (hdr *FileHeader) String() string { | ||
const format = ` | ||
Header : %s version %d | ||
Target unit %d | ||
` | ||
return fmt.Sprintf(format, hdr.Signature, hdr.Version, hdr.TargetUnit) | ||
} | ||
|
||
// ParseFile parses the given PS1 symbol file. | ||
func ParseFile(path string) (*File, error) { | ||
f, err := os.Open(path) | ||
if err != nil { | ||
return nil, errors.WithStack(err) | ||
} | ||
defer f.Close() | ||
return Parse(f) | ||
} | ||
|
||
// ParseBytes parses the given PS1 symbol file, reading from b. | ||
func ParseBytes(b []byte) (*File, error) { | ||
return Parse(bytes.NewReader(b)) | ||
} | ||
|
||
// Parse parses the given PS1 symbol file, reading from r. | ||
func Parse(r io.Reader) (*File, error) { | ||
// Parse file header. | ||
f := &File{} | ||
br := bufio.NewReader(r) | ||
hdr, err := parseFileHeader(br) | ||
if err != nil { | ||
return nil, errors.WithStack(err) | ||
} | ||
f.Hdr = hdr | ||
|
||
// Parse symbols. | ||
for { | ||
sym, err := parseSymbol(br) | ||
if err != nil { | ||
if errors.Cause(err) == io.EOF { | ||
break | ||
} | ||
return f, errors.WithStack(err) | ||
} | ||
f.Syms = append(f.Syms, sym) | ||
} | ||
|
||
return f, nil | ||
} | ||
|
||
// parseFileHeader parses and returns a PS1 symbol file header. | ||
func parseFileHeader(r io.Reader) (*FileHeader, error) { | ||
hdr := &FileHeader{} | ||
if err := struc.Unpack(r, &hdr); err != nil { | ||
return nil, errors.WithStack(err) | ||
} | ||
// Verify Smacker signature. | ||
switch string(hdr.Signature[:]) { | ||
case "MND": | ||
// valid signature. | ||
default: | ||
return nil, errors.Errorf(`invalid SYM signature; expected "MND", got %q`, hdr.Signature) | ||
} | ||
return hdr, nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,114 @@ | ||
package sym | ||
|
||
import ( | ||
"encoding/binary" | ||
"fmt" | ||
"io" | ||
|
||
"github.com/lunixbochs/struc" | ||
"github.com/pkg/errors" | ||
) | ||
|
||
// A Symbol is a PS1 symbol. | ||
type Symbol struct { | ||
// Symbol header. | ||
Hdr *SymbolHeader | ||
// Symbol body. | ||
Body SymbolBody | ||
} | ||
|
||
// String returns the string representation of the symbol. | ||
func (sym *Symbol) String() string { | ||
return fmt.Sprintf("%v %v", sym.Hdr, sym.Body) | ||
} | ||
|
||
// Size returns the size of the symbol in bytes. | ||
func (sym *Symbol) Size() int { | ||
return binary.Size(*sym.Hdr) + sym.Body.Size() | ||
} | ||
|
||
// A SymbolHeader is a PS1 symbol header. | ||
type SymbolHeader struct { | ||
// Address or value of symbol. | ||
Value uint32 `struc:"uint32,little"` | ||
// Symbol kind; specifies type of symbol body. | ||
Kind Kind `struc:"uint8,little"` | ||
} | ||
|
||
// String returns the string representation of the symbol header. | ||
func (hdr *SymbolHeader) String() string { | ||
return fmt.Sprintf("$%08x %v", hdr.Value, hdr.Kind) | ||
} | ||
|
||
// SymbolBody is the sum-type of all symbol bodies. | ||
type SymbolBody interface { | ||
// Size returns the size of the symbol body in bytes. | ||
Size() int | ||
} | ||
|
||
// parseSymbol parses and returns a PS1 symbol. | ||
func parseSymbol(r io.Reader) (*Symbol, error) { | ||
// Parse symbol header. | ||
sym := &Symbol{} | ||
hdr, err := parseSymbolHeader(r) | ||
if err != nil { | ||
return nil, errors.WithStack(err) | ||
} | ||
sym.Hdr = hdr | ||
|
||
// Parse symbol body. | ||
body, err := parseSymbolBody(r, hdr.Kind) | ||
if err != nil { | ||
return sym, errors.WithStack(err) | ||
} | ||
sym.Body = body | ||
|
||
return sym, nil | ||
} | ||
|
||
// parseSymbolHeader parses and returns a PS1 symbol header. | ||
func parseSymbolHeader(r io.Reader) (*SymbolHeader, error) { | ||
hdr := &SymbolHeader{} | ||
if err := struc.Unpack(r, &hdr); err != nil { | ||
return nil, errors.WithStack(err) | ||
} | ||
return hdr, nil | ||
} | ||
|
||
// parseSymbolBody parses and returns a PS1 symbol body. | ||
func parseSymbolBody(r io.Reader, kind Kind) (SymbolBody, error) { | ||
parse := func(body SymbolBody) (SymbolBody, error) { | ||
if err := struc.Unpack(r, body); err != nil { | ||
return nil, errors.WithStack(err) | ||
} | ||
return body, nil | ||
} | ||
switch kind { | ||
case KindOverlay: | ||
return parse(&Overlay{}) | ||
default: | ||
return nil, errors.Errorf("support for symbol kind 0x%02X not yet implemented", uint8(kind)) | ||
} | ||
} | ||
|
||
// An Overlay specifies the length and id of an file overlay (e.g. a shared | ||
// library). | ||
// | ||
// Value of the symbol header specifies the base address at which the overlay is | ||
// loaded. | ||
type Overlay struct { | ||
// Overlay length in bytes. | ||
Length uint32 `struc:"uint32,little"` | ||
// Overlay ID. | ||
ID uint32 `struc:"uint32,little"` | ||
} | ||
|
||
// String returns the string representation of the overlay symbol. | ||
func (body *Overlay) String() string { | ||
return fmt.Sprintf("length $%08x id $%x", body.Length, body.ID) | ||
} | ||
|
||
// Size returns the size of the symbol body in bytes. | ||
func (body *Overlay) Size() int { | ||
return binary.Size(*body) | ||
} |