265 lines
5.3 KiB
Go
265 lines
5.3 KiB
Go
package build
|
|
|
|
import (
|
|
"strings"
|
|
"strconv"
|
|
"fmt"
|
|
)
|
|
|
|
type Token interface {
|
|
Type() string
|
|
String() string
|
|
ValidAfter(t string) bool
|
|
Text() string
|
|
}
|
|
|
|
type TokenDelay struct {
|
|
Value int
|
|
Reset bool
|
|
}
|
|
|
|
func (itm *TokenDelay) Type() string { return "delay" }
|
|
func (itm *TokenDelay) String() string { return fmt.Sprintf("{TokenDelay Value:%d Reset:%t}", itm.Value, itm.Reset) }
|
|
|
|
func (itm *TokenDelay) ValidAfter(t string) bool {
|
|
switch t {
|
|
case "audiooffsets", "pattern", "delay", "page", "script", "tiles":
|
|
return true
|
|
}
|
|
return false
|
|
}
|
|
|
|
func (itm *TokenDelay) Text() string {
|
|
return fmt.Sprintf("delay %d reset:%t", itm.Value, itm.Reset)
|
|
}
|
|
|
|
func parseDelay(key, line string) (Token, error) {
|
|
vals := strings.Split(line, " ")
|
|
itm := &TokenDelay{}
|
|
|
|
for _, val := range vals {
|
|
if strings.Contains(val, ":") {
|
|
keyval := strings.SplitN(val, ":", 2)
|
|
if len(keyval) != 2 {
|
|
return nil, fmt.Errorf("Invalid key/value for delay: %s", val)
|
|
}
|
|
|
|
if keyval[0] != "reset" {
|
|
return nil, fmt.Errorf("Invalid key/value for delay: %s", val)
|
|
}
|
|
|
|
switch strings.ToLower(keyval[1]) {
|
|
case "true", "yes", "1":
|
|
itm.Reset = true
|
|
case "false", "no", "0":
|
|
itm.Reset = false
|
|
default:
|
|
return nil, fmt.Errorf("Invalid reset value: %s", keyval[1])
|
|
}
|
|
} else {
|
|
num, err := strconv.ParseUint(val, 0, 32)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("Invalid delay vaule: %s: %w", val, err)
|
|
}
|
|
|
|
itm.Value = int(num)
|
|
}
|
|
}
|
|
|
|
return itm, nil
|
|
}
|
|
|
|
type TokenNumValue struct {
|
|
ValType string // delay, padding, page
|
|
Value int
|
|
}
|
|
|
|
func (itm *TokenNumValue) Type() string { return itm.ValType }
|
|
func (itm *TokenNumValue) String() string { return fmt.Sprintf("{TokenNumValue ValType:%s Value:%d}", itm.ValType, itm.Value) }
|
|
|
|
func (itm *TokenNumValue) ValidAfter(t string) bool {
|
|
switch itm.ValType {
|
|
case "page":
|
|
if t == "" {
|
|
return false
|
|
}
|
|
return true
|
|
|
|
case "padding":
|
|
switch t {
|
|
case "delay", "pattern", "tiles", "script", "page":
|
|
return true
|
|
default:
|
|
return false
|
|
}
|
|
|
|
case "version":
|
|
switch t {
|
|
case "", "rom", "fullaudio":
|
|
return true
|
|
default:
|
|
return false
|
|
}
|
|
}
|
|
|
|
return false
|
|
}
|
|
|
|
func (itm *TokenNumValue) Text() string {
|
|
return fmt.Sprintf("%s %d", itm.ValType, itm.Value)
|
|
}
|
|
|
|
func parseNumValue(key, val string) (Token, error) {
|
|
v, err := strconv.Atoi(val)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("Invalid %s value: %q", key, val)
|
|
}
|
|
|
|
return &TokenNumValue{
|
|
ValType: key,
|
|
Value: int(v),
|
|
}, nil
|
|
}
|
|
|
|
type TokenStrValue struct {
|
|
ValType string
|
|
Value string
|
|
}
|
|
|
|
func (itm *TokenStrValue) Type() string { return itm.ValType }
|
|
func (itm *TokenStrValue) String() string { return fmt.Sprintf("{TokenStrVal ValType:%s Value:%q}", itm.ValType, itm.Value) }
|
|
|
|
func (itm *TokenStrValue) ValidAfter(t string) bool {
|
|
switch t {
|
|
case "", "rom", "fullaudio", "version":
|
|
return true
|
|
}
|
|
return false
|
|
}
|
|
|
|
func (itm *TokenStrValue) Text() string {
|
|
return itm.ValType+" "+itm.Value
|
|
}
|
|
|
|
func parseStrValue(key, value string) (Token, error) {
|
|
return &TokenStrValue{
|
|
ValType: key,
|
|
Value: value,
|
|
}, nil
|
|
}
|
|
|
|
type TokenAudioOffsets struct {
|
|
LeadIn uint64
|
|
Data uint64
|
|
}
|
|
|
|
func (itm *TokenAudioOffsets) Type() string { return "audiooffsets" }
|
|
func (itm *TokenAudioOffsets) String() string { return fmt.Sprintf("{ItemAudioOffsets LeadIn:%d Data:%d}", itm.LeadIn, itm.Data) }
|
|
|
|
func (itm *TokenAudioOffsets) ValidAfter(t string) bool {
|
|
switch t {
|
|
case "page", "delay", "script", "tiles", "pattern":
|
|
return true
|
|
}
|
|
return false
|
|
}
|
|
|
|
func (itm *TokenAudioOffsets) Text() string {
|
|
return fmt.Sprintf("audiooffsets leadin:%d data:%d", itm.LeadIn, itm.Data)
|
|
}
|
|
|
|
func parseAudioOffsets(key, line string) (Token, error) {
|
|
vals := strings.Split(line, " ")
|
|
itm := &TokenAudioOffsets{}
|
|
for _, keyval := range vals {
|
|
pair := strings.Split(keyval, ":")
|
|
if len(pair) != 2 {
|
|
return nil, fmt.Errorf("invalid syntax: %q", keyval)
|
|
}
|
|
|
|
num, err := strconv.ParseUint(pair[1], 0, 64)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
switch pair[0] {
|
|
case "leadin":
|
|
itm.LeadIn = num
|
|
case "data":
|
|
itm.Data = num
|
|
default:
|
|
return nil, fmt.Errorf("unknown key: %s", pair[0])
|
|
}
|
|
}
|
|
|
|
return itm, nil
|
|
}
|
|
|
|
type TokenData struct {
|
|
ValType string
|
|
Bank int
|
|
Addr int
|
|
File string
|
|
}
|
|
|
|
func (itm *TokenData) Type() string { return itm.ValType }
|
|
func (itm *TokenData) String() string {
|
|
return fmt.Sprintf("{TokenData ValType:%s Bank:0x%02X Addr:0x%02X File:%q}",
|
|
itm.ValType,
|
|
itm.Bank,
|
|
itm.Addr,
|
|
itm.File,
|
|
)
|
|
}
|
|
|
|
func (itm *TokenData) ValidAfter(t string) bool {
|
|
switch t {
|
|
case "page", "delay", "script", "tiles", "pattern":
|
|
return true
|
|
}
|
|
return false
|
|
}
|
|
|
|
func (itm *TokenData) Text() string {
|
|
return fmt.Sprintf("%s bank:0x%02X addr:0x%02X file:%q",
|
|
itm.ValType,
|
|
itm.Bank,
|
|
itm.Addr,
|
|
itm.File,
|
|
)
|
|
}
|
|
|
|
func parseData(tokType, vals string) (Token, error) {
|
|
args, err := pKeyVals(vals)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
itm := &TokenData{ValType: tokType}
|
|
for key, value := range args {
|
|
switch key {
|
|
case "bank":
|
|
val, err := strconv.ParseUint(value, 0, 8)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("%s bank value error: %w", key, err)
|
|
}
|
|
itm.Bank = int(val)
|
|
|
|
case "addr":
|
|
val, err := strconv.ParseUint(value, 0, 8)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("%s addr value error: %w", key, err)
|
|
}
|
|
itm.Addr = int(val)
|
|
|
|
case "file":
|
|
itm.File = value
|
|
|
|
default:
|
|
return nil, fmt.Errorf("%s unknown key: %q", tokType, key)
|
|
}
|
|
}
|
|
|
|
return itm, nil
|
|
}
|