aboutsummaryrefslogtreecommitdiff
path: root/parameters.go
diff options
context:
space:
mode:
Diffstat (limited to 'parameters.go')
-rw-r--r--parameters.go255
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
}