diff options
Diffstat (limited to 'parameters.go')
-rw-r--r-- | parameters.go | 255 |
1 files changed, 187 insertions, 68 deletions
diff --git a/parameters.go b/parameters.go index 06202f9..5dffc1c 100644 --- a/parameters.go +++ b/parameters.go @@ -6,7 +6,7 @@ import ( "strings" ) -func parseOffset(param string) (string, uint16, error) { +func parseOffset(param string) (string, uint32, error) { if strings.Contains(param, "+") { labelParts := strings.Split(param, "+") if len(labelParts) != 2 { @@ -16,17 +16,23 @@ func parseOffset(param string) (string, uint16, error) { ) } labelWithoutOffset := labelParts[0] - o, err := strconv.ParseUint(labelParts[1], 0, 16) + o, err := strconv.ParseUint(labelParts[1], 0, 32) if err != nil { return "", 0, fmt.Errorf("Error while parsing label offset: %w", err) } - offset := uint16(o) + offset := uint32(o) return labelWithoutOffset, offset, nil } return param, 0, nil } -func Reg8(_ *Labels, lastAbsoluteLabel string, _ *Definitions, param string) (uint16, error) { +func Reg8( + _ *Labels, + lastAbsoluteLabel string, + _ *Definitions, + _ uint32, + param string, +) (uint32, error) { switch param { case "A": return 7, nil @@ -48,35 +54,65 @@ func Reg8(_ *Labels, lastAbsoluteLabel string, _ *Definitions, param string) (ui return 0, fmt.Errorf("Invalid reg8") } -func A(_ *Labels, lastAbsoluteLabel string, _ *Definitions, param string) (uint16, error) { +func A( + _ *Labels, + lastAbsoluteLabel string, + _ *Definitions, + _ uint32, + param string, +) (uint32, error) { if param == "A" { return 0, nil } return 0, fmt.Errorf("Invalid A") } -func HL(_ *Labels, lastAbsoluteLabel string, _ *Definitions, param string) (uint16, error) { +func HL( + _ *Labels, + lastAbsoluteLabel string, + _ *Definitions, + _ uint32, + param string, +) (uint32, error) { if param == "HL" { return 0, nil } return 0, fmt.Errorf("Invalid HL") } -func SP(_ *Labels, lastAbsoluteLabel string, _ *Definitions, param string) (uint16, error) { +func SP( + _ *Labels, + lastAbsoluteLabel string, + _ *Definitions, + _ uint32, + param string, +) (uint32, error) { if param == "SP" { return 0, nil } return 0, fmt.Errorf("Invalid SP") } -func IndirectC(_ *Labels, lastAbsoluteLabel string, _ *Definitions, param string) (uint16, error) { +func IndirectC( + _ *Labels, + lastAbsoluteLabel string, + _ *Definitions, + _ uint32, + param string, +) (uint32, error) { if param == "(C)" { return 0, nil } return 0, fmt.Errorf("Invalid (C)") } -func Reg16(_ *Labels, lastAbsoluteLabel string, _ *Definitions, param string) (uint16, error) { +func Reg16( + _ *Labels, + lastAbsoluteLabel string, + _ *Definitions, + _ uint32, + param string, +) (uint32, error) { switch param { case "BC": return 0, nil @@ -97,28 +133,36 @@ func Raw8( labels *Labels, lastAbsoluteLabel string, defs *Definitions, + currentAddress uint32, param string, -) (uint16, error) { +) (uint32, error) { if strings.HasPrefix(param, "high(") && strings.HasSuffix(param, ")") { - v, err := Raw16(labels, lastAbsoluteLabel, defs, param[5:len(param)-1]) + v, err := Raw16(labels, lastAbsoluteLabel, defs, currentAddress, param[5:len(param)-1]) if err != nil { return 0, err } - return uint16(v >> 8), nil + return uint32(v >> 8), nil } if strings.HasPrefix(param, "low(") && strings.HasSuffix(param, ")") { - v, err := Raw16(labels, lastAbsoluteLabel, defs, param[4:len(param)-1]) + v, err := Raw16(labels, lastAbsoluteLabel, defs, currentAddress, param[4:len(param)-1]) if err != nil { return 0, err } - return uint16(v & 0xff), nil + return uint32(v & 0xff), nil } if strings.HasPrefix(param, "inv(") && strings.HasSuffix(param, ")") { - v, err := Raw8(labels, lastAbsoluteLabel, defs, param[4:len(param)-1]) + v, err := Raw8(labels, lastAbsoluteLabel, defs, currentAddress, param[4:len(param)-1]) if err != nil { return 0, err } - return uint16((256 / v) & 0xff), nil + return uint32((256 / v) & 0xff), nil + } + if strings.HasPrefix(param, "bank(") && strings.HasSuffix(param, ")") { + v, err := ROMAddress(labels, lastAbsoluteLabel, defs, currentAddress, param[5:len(param)-1]) + if err != nil { + return 0, err + } + return uint32((v / 0x4000) & 0xff), nil } if strings.HasPrefix(param, "$") { param = strings.ToUpper(strings.TrimPrefix(param, "$")) @@ -126,7 +170,7 @@ func Raw8( if len(param) > 2 { return 0, fmt.Errorf("%s is > 8bit", param) } - return uint16(res), nil + return uint32(res), nil } varWithoutOffset, offset, err := parseOffset(param) @@ -148,54 +192,69 @@ func Raw8( ) } - if uint16(res)+offset > 0xff { + if uint32(res)+offset > 0xff { return 0, fmt.Errorf( "overflow: $%s (0x%02x) + 0x%02x exceeds 0xff", varWithoutOffset, - uint16(res), + uint32(res), offset, ) } - return uint16(res) + offset, nil + return uint32(res) + offset, nil } if strings.HasPrefix(param, "0x") && len(param) > 4 { return 0, fmt.Errorf("%s is > 8bit", param) } res, err := strconv.ParseUint(param, 0, 8) - return uint16(res), err + return uint32(res), err } func Raw16( labels *Labels, lastAbsoluteLabel string, defs *Definitions, + currentAddress uint32, param string, -) (uint16, error) { +) (uint32, error) { + if strings.HasPrefix(param, "ptr(") && strings.HasSuffix(param, ")") { + v, err := ROMAddress(labels, lastAbsoluteLabel, defs, currentAddress, param[4:len(param)-1]) + if err != nil { + return 0, err + } + + bank := v / 0x4000 + if bank == 0 { + return v, nil + } + + return v - bank*0x4000 + 0x4000, nil + } + if strings.Contains(param, "-") { spl := strings.Split(param, "-") - v, err := Raw16(labels, lastAbsoluteLabel, defs, spl[0]) + v, err := Raw16(labels, lastAbsoluteLabel, defs, currentAddress, spl[0]) if err != nil { return 0, err } result := v for _, arg := range spl[1:] { - v, err := Raw16(labels, lastAbsoluteLabel, defs, arg) + v, err := Raw16(labels, lastAbsoluteLabel, defs, currentAddress, arg) if err != nil { return 0, err } result -= v } - return result, nil + return result & 0xffff, nil } if strings.HasPrefix(param, "$") { param = strings.ToUpper(strings.TrimPrefix(param, "$")) if res, err := strconv.ParseUint(param, 16, 16); err == nil { - return uint16(res), nil + return uint32(res & 0xffff), nil } varWithoutOffset, offset, err := parseOffset(param) @@ -221,74 +280,63 @@ func Raw16( return 0, fmt.Errorf( "overflow: $%s (0x%04x) + 0x%04x exceeds 0xffff", varWithoutOffset, - uint16(res), + uint32(res), offset, ) } - return uint16(res) + offset, nil + return uint32(res) + offset, nil } - if strings.HasPrefix(param, "=") { - labelWithoutOffset, offset, err := parseOffset(param[1:]) - if err != nil { - return 0, err - } - - if labels == nil { - return 0, nil - } + romAddr, err := ROMAddress(labels, lastAbsoluteLabel, defs, currentAddress, param) + if err == nil { + currentBank := currentAddress / 0x4000 + romAddrBank := romAddr / 0x4000 - if strings.HasPrefix(labelWithoutOffset, ".") { - if lastAbsoluteLabel == "" { - return 0, fmt.Errorf( - "Relative label \"%s\" referenced outside of parent", - labelWithoutOffset, - ) - } - labelWithoutOffset = lastAbsoluteLabel + labelWithoutOffset + if romAddrBank == 0 { + return romAddr, nil } - label := strings.ToUpper(strings.TrimPrefix(labelWithoutOffset, "=")) - labelValue, ok := (*labels)[label] - if !ok { - return 0, fmt.Errorf("Label \"%s\" not found", label) - } - - // TODO: Manage when multiple MBC - if labelValue > 0x8000 { - panic("Switchable ROM banks are not implemented yet") + if currentBank != romAddrBank { + return 0, fmt.Errorf( + "Cannot use an address from another bank (or bank 0). Please change the bank using bank(x) and get the raw bankless ptr using ptr(x). %s in bank %v, but current address is %v", + param, + romAddrBank, + currentBank, + ) } - return uint16(labelValue) + offset, nil + return romAddr - romAddrBank*0x4000 + 0x4000, nil } res, err := strconv.ParseUint(param, 0, 16) - return uint16(res), err + return uint32(res), err } func Raw16MacroRelativeLabel( labels *Labels, lastAbsoluteLabel string, defs *Definitions, + currentAddress uint32, param string, -) (uint16, error) { +) (uint32, error) { if !strings.HasPrefix(param, "=$") { return 0, fmt.Errorf( "label \"%s\" is external to the macro", param, ) } - return Raw16(labels, lastAbsoluteLabel, defs, param) + return Raw16(labels, lastAbsoluteLabel, defs, currentAddress, param) } func Reg16Indirect( _ *Labels, lastAbsoluteLabel string, _ *Definitions, + _ uint32, param string, -) (uint16, error) { +) (uint32, error) { switch param { case "(BC)": return 0, nil @@ -306,8 +354,9 @@ func Raw8Indirect( labels *Labels, lastAbsoluteLabel string, defs *Definitions, + currentAddress uint32, param string, -) (uint16, error) { +) (uint32, error) { if strings.HasPrefix(param, "$") { param = strings.ToUpper(strings.TrimPrefix(param, "$")) @@ -320,14 +369,14 @@ func Raw8Indirect( if !ok { return 0, fmt.Errorf("$%s is of type %T but Indirect8bb is expected", param, definition) } - return uint16(res), nil + return uint32(res), nil } if len(param) < 2 || param[0] != '(' || param[len(param)-1] != ')' { return 0, fmt.Errorf("Invalid raw8indirect") } - res, err := Raw8(labels, lastAbsoluteLabel, defs, param[1:len(param)-1]) + res, err := Raw8(labels, lastAbsoluteLabel, defs, currentAddress, param[1:len(param)-1]) if err == nil { return res, nil } @@ -338,8 +387,9 @@ func Raw16Indirect( labels *Labels, lastAbsoluteLabel string, defs *Definitions, + currentAddress uint32, param string, -) (uint16, error) { +) (uint32, error) { if strings.HasPrefix(param, "$") { param = strings.ToUpper(strings.TrimPrefix(param, "$")) @@ -356,16 +406,79 @@ func Raw16Indirect( if !ok { return 0, fmt.Errorf("$%s is of type %T but Indirect16b expected", param, definition) } - return uint16(res), nil + return uint32(res), nil } if len(param) < 2 || param[0] != '(' || param[len(param)-1] != ')' { return 0, fmt.Errorf("Invalid raw16indirect") } - return Raw16(labels, lastAbsoluteLabel, defs, param[1:len(param)-1]) + return Raw16(labels, lastAbsoluteLabel, defs, currentAddress, param[1:len(param)-1]) } -func Condition(_ *Labels, lastAbsoluteLabel string, _ *Definitions, param string) (uint16, error) { +func ROMAddress( + labels *Labels, + lastAbsoluteLabel string, + defs *Definitions, + currentAddress uint32, + param string, +) (uint32, error) { + if strings.HasPrefix(param, "=") { + labelWithoutOffset, offset, err := parseOffset(param[1:]) + if err != nil { + return 0, err + } + + if labels == nil { + return 0, nil + } + + if strings.HasPrefix(labelWithoutOffset, ".") { + if lastAbsoluteLabel == "" { + return 0, fmt.Errorf( + "Relative label \"%s\" referenced outside of parent", + labelWithoutOffset, + ) + } + labelWithoutOffset = lastAbsoluteLabel + labelWithoutOffset + } + + label := strings.ToUpper(strings.TrimPrefix(labelWithoutOffset, "=")) + labelValue, ok := (*labels)[label] + if !ok { + return 0, fmt.Errorf("Label \"%s\" not found", label) + } + + return uint32(labelValue) + offset, nil + } + + if len(param) != 7 || param[2] != ':' { + return 0, fmt.Errorf("Couldn't parse \"%s\" as a ROM addr", param) + } + + bank, err := strconv.ParseUint(param[0:2], 16, 8) + if err != nil { + return 0, fmt.Errorf( + "Couldn't parse bank number in \"%s\"", param, + ) + } + + addr, err := strconv.ParseUint(param[3:], 16, 8) + if err != nil { + return 0, fmt.Errorf( + "Couldn't parse address in \"%s\"", param, + ) + } + + return uint32(bank*0x4000 + addr), nil +} + +func Condition( + _ *Labels, + lastAbsoluteLabel string, + _ *Definitions, + _ uint32, + param string, +) (uint32, error) { switch param { case "NZ": return 0, nil @@ -379,7 +492,13 @@ func Condition(_ *Labels, lastAbsoluteLabel string, _ *Definitions, param string return 0, fmt.Errorf("Invalid condition") } -func BitOrdinal(_ *Labels, lastAbsoluteLabel string, _ *Definitions, param string) (uint16, error) { +func BitOrdinal( + _ *Labels, + lastAbsoluteLabel string, + _ *Definitions, + _ uint32, + param string, +) (uint32, error) { res, err := strconv.ParseUint(param, 0, 3) - return uint16(res), err + return uint32(res), err } |