Skip to content

Commit

Permalink
snes: add ErrUnmappedAddress case for mapping.Translate() to make it …
Browse files Browse the repository at this point in the history
…obvious when attempting to access unmapped addresses
  • Loading branch information
JamesDunne committed Jun 22, 2021
1 parent a6fd75c commit 520cc99
Show file tree
Hide file tree
Showing 8 changed files with 97 additions and 95 deletions.
60 changes: 29 additions & 31 deletions snes/mapping/exhirom/mapping.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,106 +4,105 @@ import "sni/snes/mapping/util"

// https://thepoorstudenthobbyist.com/2019/05/18/custom-pcb-explanation/#exhirom

func BusAddressToPak(busAddr uint32) uint32 {
func BusAddressToPak(busAddr uint32) (pakAddr uint32, err error) {
if busAddr >= 0xC00000 && busAddr < 0x1_000000 {
// program area 1
// ROM access: $C0:0000-$FF:FFFF
rom := (busAddr & 0x3FFFFF) + 0x000000
return rom
return rom, nil
} else if busAddr >= 0xA00000 && busAddr < 0xC00000 {
if busAddr&0x8000 != 0 {
// program area 1
// ROM access: $A0:8000-$BF:FFFF
rom := util.BankToLinear(busAddr&0x3F7FFF) + 0x000000
return rom
return rom, nil
} else if busAddr&0x7FFF >= 0x6000 {
// TODO: A0-AF, B0-BF mirroring?
// SRAM access: $A0:6000-$BF:7FFF
bank := (busAddr >> 16) - 0xA0
sram := ((bank << 13) + (busAddr & 0x1FFF)) + 0xE00000
return sram
return sram, nil
} else if busAddr&0xFFFF < 0x2000 {
// Lower 8KiB of WRAM: $A0:0000-$BF:1FFF
wram := (busAddr & 0x1FFF) + 0xF50000
return wram
return wram, nil
}
} else if busAddr >= 0x800000 && busAddr < 0xA00000 {
if busAddr&0x8000 != 0 {
// program area 1
// ROM access: $80:8000-$9F:FFFF
rom := util.BankToLinear(busAddr&0x3F7FFF) + 0x000000
return rom
return rom, nil
} else if busAddr&0xFFFF < 0x2000 {
// Lower 8KiB of WRAM: $80:0000-$9F:1FFF
wram := (busAddr & 0x1FFF) + 0xF50000
return wram
return wram, nil
}
} else if busAddr >= 0x7E0000 && busAddr < 0x800000 {
// WRAM access:
wram := (busAddr - 0x7E0000) + 0xF50000
return wram
return wram, nil
} else if busAddr >= 0x400000 && busAddr < 0x7E0000 {
// program area 2
// ROM access: $40:0000-$7D:FFFF
rom := (busAddr & 0x3FFFFF) + 0x400000
return rom
return rom, nil
} else if busAddr >= 0x3E0000 && busAddr < 0x400000 {
if busAddr&0x8000 != 0 {
// program area 3 $3E-3F
// ROM access: $3E:8000-$3F:FFFF
rom := util.BankToLinear(busAddr&0x3F7FFF) + 0x400000
return rom
return rom, nil
} else if busAddr&0xFFFF < 0x2000 {
// Lower 8KiB of WRAM: $00:0000-$1F:1FFF
wram := (busAddr & 0x1FFF) + 0xF50000
return wram
return wram, nil
}
} else if busAddr >= 0x200000 && busAddr < 0x3E0000 {
if busAddr&0x8000 != 0 {
// program area 2
// ROM access: $20:8000-$3D:FFFF
rom := util.BankToLinear(busAddr&0x3F7FFF) + 0x400000
return rom
return rom, nil
} else if busAddr&0xFFFF < 0x2000 {
// Lower 8KiB of WRAM: $00:0000-$1F:1FFF
wram := (busAddr & 0x1FFF) + 0xF50000
return wram
return wram, nil
}
} else if busAddr < 0x200000 {
if busAddr&0x8000 != 0 {
// program area 2
// ROM access: $00:8000-$1F:FFFF
rom := util.BankToLinear(busAddr&0x3F7FFF) + 0x400000
return rom
return rom, nil
} else if busAddr&0xFFFF < 0x2000 {
// Lower 8KiB of WRAM: $00:0000-$1F:1FFF
wram := (busAddr & 0x1FFF) + 0xF50000
return wram
return wram, nil
}
}
return busAddr
return 0, util.ErrUnmappedAddress
}

func PakAddressToBus(pakAddr uint32) uint32 {
// WRAM is easy:
func PakAddressToBus(pakAddr uint32) (busAddr uint32, err error) {
if pakAddr >= 0xF50000 {
// WRAM is easy:
// mirror bank $F7..FF back down into WRAM because these banks in FX Pak Pro space
// are not available on the SNES bus; they are copies of otherwise inaccessible memory
// like VRAM, CGRAM, OAM, etc.:
return ((pakAddr - 0xF50000) & 0x01FFFF) + 0x7E0000
}
// SRAM is a little more complex, but not much:
if pakAddr >= 0xE00000 && pakAddr < 0xF00000 {
busAddr = ((pakAddr - 0xF50000) & 0x01FFFF) + 0x7E0000
return
} else if pakAddr >= 0xE00000 && pakAddr < 0xF00000 {
// SRAM is a little more complex, but not much:
// TODO: handle A0-AF, B0-BF mirroring depending on SRAM size
// A0:6000-7FFF to BF:6000-7FFF
busAddr := pakAddr - 0xE00000
busAddr = pakAddr - 0xE00000
offs := busAddr & 0x1FFF
bank := (busAddr >> 13) & 0x1F
busAddr = ((0xA0 + bank) << 16) + (offs + 0x6000)
return busAddr
}
// ROM access:
if pakAddr < 0xE00000 {
var busAddr uint32
return
} else if pakAddr < 0xE00000 {
// ROM access:
if pakAddr >= 0x800000 {
// map FX Pak Pro $800000 to SlowROM banks $00-3F (mirrored to $40..$5F)
busAddr = (pakAddr - 0x800000) & 0x3FFFFF
Expand Down Expand Up @@ -132,8 +131,7 @@ func PakAddressToBus(pakAddr uint32) uint32 {
// $C0:0000-FFFF to $FF:0000-FFFF
busAddr = 0xC00000 + (pakAddr & 0x3FFFFF)
}
return busAddr
return
}
// /shrug
return pakAddr
return 0, util.ErrUnmappedAddress
}
4 changes: 2 additions & 2 deletions snes/mapping/exhirom/mapping_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -325,7 +325,7 @@ func TestPakAddressToBus(t *testing.T) {
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if got := PakAddressToBus(tt.args.pakAddr); got != tt.want {
if got, _ := PakAddressToBus(tt.args.pakAddr); got != tt.want {
t.Errorf("PakAddressToBus() = %06x, want %06x", got, tt.want)
}
})
Expand Down Expand Up @@ -708,7 +708,7 @@ func TestBusAddressToPak(t *testing.T) {
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if got := BusAddressToPak(tt.args.busAddr); got != tt.want {
if got, _ := BusAddressToPak(tt.args.busAddr); got != tt.want {
t.Errorf("BusAddressToPak() = %v, want %v", got, tt.want)
}
})
Expand Down
53 changes: 27 additions & 26 deletions snes/mapping/hirom/mapping.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,111 +4,112 @@ import (
"sni/snes/mapping/util"
)

func BusAddressToPak(busAddr uint32) uint32 {
func BusAddressToPak(busAddr uint32) (pakAddr uint32, err error) {
if busAddr >= 0xFE0000 && busAddr < 0x1_000000 {
// ROM access: $FE:0000-$FF:FFFF
rom := (busAddr & 0x3FFFFF) + 0x000000
return rom
return rom, nil
} else if busAddr >= 0xC00000 && busAddr < 0xFE0000 {
// ROM access: $C0:0000-$FD:FFFF
rom := (busAddr & 0x3FFFFF) + 0x000000
return rom
return rom, nil
} else if busAddr >= 0xA00000 && busAddr < 0xC00000 {
if busAddr&0x8000 != 0 {
// ROM access: $A0:8000-$BF:FFFF
rom := util.BankToLinear(busAddr&0x3F7FFF) + 0x000000
return rom
return rom, nil
} else if busAddr&0x7FFF >= 0x6000 {
// TODO: A0-AF, B0-BF mirroring?
// SRAM access: $A0:6000-$BF:7FFF
bank := (busAddr >> 16) - 0xA0
sram := ((bank << 13) + (busAddr & 0x1FFF)) + 0xE00000
return sram
return sram, nil
} else if busAddr&0xFFFF < 0x2000 {
// Lower 8KiB of WRAM: $A0:0000-$BF:1FFF
wram := (busAddr & 0x1FFF) + 0xF50000
return wram
return wram, nil
}
} else if busAddr >= 0x800000 && busAddr < 0xA00000 {
if busAddr&0x8000 != 0 {
// ROM access: $80:8000-$9F:FFFF
rom := util.BankToLinear(busAddr&0x3F7FFF) + 0x000000
return rom
return rom, nil
} else if busAddr&0xFFFF < 0x2000 {
// Lower 8KiB of WRAM: $80:0000-$9F:1FFF
wram := (busAddr & 0x1FFF) + 0xF50000
return wram
return wram, nil
}
} else if busAddr >= 0x7E0000 && busAddr < 0x800000 {
// WRAM access:
wram := (busAddr - 0x7E0000) + 0xF50000
return wram
return wram, nil
} else if busAddr >= 0x400000 && busAddr < 0x7E0000 {
// ROM access: $40:0000-$7D:FFFF
rom := (busAddr & 0x3FFFFF) + 0x000000
return rom
return rom, nil
} else if busAddr >= 0x200000 && busAddr < 0x400000 {
if busAddr&0x8000 != 0 {
// ROM access: $20:8000-$3F:FFFF
rom := util.BankToLinear(busAddr&0x3F7FFF) + 0x000000
return rom
return rom, nil
} else if busAddr&0x7FFF >= 0x6000 {
// TODO: 20-2F, 30-3F mirroring?
// SRAM access: $20:6000-$3F:7FFF
bank := (busAddr >> 16) - 0x20
sram := ((bank << 13) + (busAddr & 0x1FFF)) + 0xE00000
return sram
return sram, nil
} else if busAddr&0xFFFF < 0x2000 {
// Lower 8KiB of WRAM: $00:0000-$1F:1FFF
wram := (busAddr & 0x1FFF) + 0xF50000
return wram
return wram, nil
}
} else if busAddr >= 0x000000 && busAddr < 0x200000 {
if busAddr&0x8000 != 0 {
// ROM access: $00:8000-$1F:FFFF
rom := util.BankToLinear(busAddr&0x3F7FFF) + 0x000000
return rom
return rom, nil
} else if busAddr&0xFFFF < 0x2000 {
// Lower 8KiB of WRAM: $00:0000-$1F:1FFF
wram := (busAddr & 0x1FFF) + 0xF50000
return wram
return wram, nil
}
}
return busAddr
return 0, util.ErrUnmappedAddress
}

func PakAddressToBus(pakAddr uint32) uint32 {
func PakAddressToBus(pakAddr uint32) (busAddr uint32, err error) {
// WRAM is easy:
if pakAddr >= 0xF50000 {
// mirror bank $F7..FF back down into WRAM because these banks in FX Pak Pro space
// are not available on the SNES bus; they are copies of otherwise inaccessible memory
// like VRAM, CGRAM, OAM, etc.:
return ((pakAddr - 0xF50000) & 0x01FFFF) + 0x7E0000
busAddr = ((pakAddr - 0xF50000) & 0x01FFFF) + 0x7E0000
return
} else if pakAddr >= 0xE00000 && pakAddr < 0xF00000 {
// SRAM is a little more complex, but not much:
// TODO: handle A0-AF, B0-BF mirroring depending on SRAM size
// bank $A0-$BF
busAddr := pakAddr - 0xE00000
busAddr = pakAddr - 0xE00000
offs := busAddr & 0x1FFF
bank := (busAddr >> 13) & 0x1F
busAddr = ((0xA0 + bank) << 16) + (offs + 0x6000)
return busAddr
return
} else if pakAddr >= 0x200000 && pakAddr < 0xE00000 {
busAddr := pakAddr & 0x3FFFFF
busAddr = pakAddr & 0x3FFFFF
// Accessing memory in banks $80-$FF is done at 3.58 MHz (120 ns) if the value at address $420D (hardware register) is set to 1.
// Starting at $C0 gets us the full linear mapping of ROM without having to cut up in $8000 sized chunks:
busAddr = 0xC00000 + busAddr
return busAddr
return
} else if pakAddr < 0x200000 {
// ROM access:
// HiROM is limited to $40 full banks

// use SlowROM banks $00-$3F:
busAddr := pakAddr & 0x3FFFFF
busAddr = pakAddr & 0x3FFFFF
offs := busAddr & 0x7FFF
bank := busAddr >> 15
busAddr = ((0x00 + bank) << 16) + (offs | 0x8000)
return busAddr
return
}
// /shrug
return pakAddr
return 0, util.ErrUnmappedAddress
}
4 changes: 2 additions & 2 deletions snes/mapping/hirom/mapping_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -332,7 +332,7 @@ func TestPakAddressToBus(t *testing.T) {
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if got := PakAddressToBus(tt.args.pakAddr); got != tt.want {
if got, _ := PakAddressToBus(tt.args.pakAddr); got != tt.want {
t.Errorf("PakAddressToBus() = %06x, want %06x", got, tt.want)
}
})
Expand Down Expand Up @@ -741,7 +741,7 @@ func TestBusAddressToPak(t *testing.T) {
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if got := BusAddressToPak(tt.args.busAddr); got != tt.want {
if got, _ := BusAddressToPak(tt.args.busAddr); got != tt.want {
t.Errorf("BusAddressToPak() = %v, want %v", got, tt.want)
}
})
Expand Down
Loading

0 comments on commit 520cc99

Please sign in to comment.