From 379a9b86fd7e196cbfa9cf4713bc39c9fb049662 Mon Sep 17 00:00:00 2001 From: jsd1982 Date: Sun, 20 Jun 2021 18:16:19 -0500 Subject: [PATCH] snes: exhirom: complete BusAddressToPak mapping --- snes/mapping/exhirom/mapping.go | 87 ++++++- snes/mapping/exhirom/mapping_test.go | 338 +++++++++++++++++++++++++++ 2 files changed, 417 insertions(+), 8 deletions(-) diff --git a/snes/mapping/exhirom/mapping.go b/snes/mapping/exhirom/mapping.go index d39b786..cae8322 100644 --- a/snes/mapping/exhirom/mapping.go +++ b/snes/mapping/exhirom/mapping.go @@ -1,18 +1,83 @@ package exhirom -import ( - "sni/snes/mapping/util" -) +import "sni/snes/mapping/util" // https://thepoorstudenthobbyist.com/2019/05/18/custom-pcb-explanation/#exhirom func BusAddressToPak(busAddr uint32) uint32 { - if busAddr&0x8000 == 0 { - if busAddr >= 0x700000 && busAddr < 0x7E0000 { - sram := util.BankToLinear(busAddr-0x700000) + 0xE00000 + if busAddr >= 0xC00000 && busAddr < 0x1_000000 { + // program area 1 + // ROM access: $C0:0000-$FF:FFFF + rom := (busAddr & 0x3FFFFF) + 0x000000 + return rom + } 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 + } 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 - } else if busAddr >= 0x7E0000 && busAddr < 0x800000 { - wram := (busAddr - 0x7E0000) + 0xF50000 + } else if busAddr&0xFFFF < 0x2000 { + // Lower 8KiB of WRAM: $A0:0000-$BF:1FFF + wram := (busAddr & 0x1FFF) + 0xF50000 + return wram + } + } 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 + } else if busAddr&0xFFFF < 0x2000 { + // Lower 8KiB of WRAM: $80:0000-$9F:1FFF + wram := (busAddr & 0x1FFF) + 0xF50000 + return wram + } + } else if busAddr >= 0x7E0000 && busAddr < 0x800000 { + // WRAM access: + wram := (busAddr - 0x7E0000) + 0xF50000 + return wram + } else if busAddr >= 0x400000 && busAddr < 0x7E0000 { + // program area 2 + // ROM access: $40:0000-$7D:FFFF + rom := (busAddr & 0x3FFFFF) + 0x400000 + return rom + } 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 + } else if busAddr&0xFFFF < 0x2000 { + // Lower 8KiB of WRAM: $00:0000-$1F:1FFF + wram := (busAddr & 0x1FFF) + 0xF50000 + return wram + } + } 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 + } else if busAddr&0xFFFF < 0x2000 { + // Lower 8KiB of WRAM: $00:0000-$1F:1FFF + wram := (busAddr & 0x1FFF) + 0xF50000 + return wram + } + } else if busAddr >= 0x000000 && busAddr < 0x200000 { + if busAddr&0x8000 != 0 { + // program area 2 + // ROM access: $00:8000-$1F:FFFF + rom := util.BankToLinear(busAddr&0x3F7FFF) + 0x400000 + return rom + } else if busAddr&0xFFFF < 0x2000 { + // Lower 8KiB of WRAM: $00:0000-$1F:1FFF + wram := (busAddr & 0x1FFF) + 0xF50000 return wram } } @@ -29,6 +94,7 @@ func PakAddressToBus(pakAddr uint32) uint32 { } // SRAM is a little more complex, but not much: if pakAddr >= 0xE00000 && pakAddr < 0xF00000 { + // A0:6000-7FFF to BF:6000-7FFF busAddr := pakAddr - 0xE00000 offs := busAddr & 0x1FFF bank := (busAddr >> 13) & 0x1F @@ -47,18 +113,23 @@ func PakAddressToBus(pakAddr uint32) uint32 { if bank >= 0x7E { bank += 0x80 } + // $00:8000-FFFF to $7D:8000-FFFF + // $FE:8000-FFFF to $FF:8000-FFFF busAddr = (bank << 16) + (offs | 0x8000) } else if pakAddr >= 0x7E0000 && pakAddr < 0x800000 { // program ROM area 3 is top half of banks $3E and $3F busAddr = pakAddr - 0x7E0000 offs := busAddr & 0x7FFF bank := 0x3E + (busAddr >> 15) + // $3E:8000-FFFF to $3F:8000-FFFF busAddr = (bank << 16) + (offs | 0x8000) } else if pakAddr >= 0x400000 && pakAddr < 0x7E0000 { // program ROM area 2 is full banks $40-$7D + // $40:0000-FFFF to $7D:0000-FFFF busAddr = 0x400000 + (pakAddr & 0x3FFFFF) } else { // program ROM area 1 is full banks $C0-$FF + // $C0:0000-FFFF to $FF:0000-FFFF busAddr = 0xC00000 + (pakAddr & 0x3FFFFF) } return busAddr diff --git a/snes/mapping/exhirom/mapping_test.go b/snes/mapping/exhirom/mapping_test.go index d49e1d1..a605cdb 100644 --- a/snes/mapping/exhirom/mapping_test.go +++ b/snes/mapping/exhirom/mapping_test.go @@ -331,3 +331,341 @@ func TestPakAddressToBus(t *testing.T) { }) } } + +func TestBusAddressToPak(t *testing.T) { + type args struct { + busAddr uint32 + } + tests := []struct { + name string + args args + want uint32 + }{ + // banks $80-FF: + { + name: "ROM bank $FE:0000", + args: args{ + busAddr: 0xFE0000, + }, + want: 0x3E0000, + }, + { + name: "ROM bank $FE:FFFF", + args: args{ + busAddr: 0xFEFFFF, + }, + want: 0x3EFFFF, + }, + { + name: "ROM bank $FF:0000", + args: args{ + busAddr: 0xFF0000, + }, + want: 0x3F0000, + }, + { + name: "ROM bank $FF:FFFF", + args: args{ + busAddr: 0xFFFFFF, + }, + want: 0x3FFFFF, + }, + { + name: "ROM bank $C0:0000", + args: args{ + busAddr: 0xC00000, + }, + want: 0x000000, + }, + { + name: "ROM bank $C0:FFFF", + args: args{ + busAddr: 0xC0FFFF, + }, + want: 0x00FFFF, + }, + { + name: "ROM bank $FD:0000", + args: args{ + busAddr: 0xFD0000, + }, + want: 0x3D0000, + }, + { + name: "ROM bank $FD:FFFF", + args: args{ + busAddr: 0xFDFFFF, + }, + want: 0x3DFFFF, + }, + { + name: "ROM bank $A0:8000", + args: args{ + busAddr: 0xA08000, + }, + want: 0x100000, + }, + { + name: "ROM bank $A1:8000", + args: args{ + busAddr: 0xA18000, + }, + want: 0x108000, + }, + { + name: "SRAM bank $A0:6000", + args: args{ + busAddr: 0xA06000, + }, + want: 0xE00000, + }, + { + name: "SRAM bank $A1:6000", + args: args{ + busAddr: 0xA16000, + }, + want: 0xE02000, + }, + { + name: "SRAM bank $BF:6000", + args: args{ + busAddr: 0xBF6000, + }, + want: 0xE3E000, + }, + { + name: "SRAM bank $BF:7FFF", + args: args{ + busAddr: 0xBF7FFF, + }, + want: 0xE3FFFF, + }, + { + name: "ROM bank $80:8000", + args: args{ + busAddr: 0x808000, + }, + want: 0x000000, + }, + { + name: "ROM bank $81:8000", + args: args{ + busAddr: 0x818000, + }, + want: 0x008000, + }, + { + name: "WRAM bank $80:0000", + args: args{ + busAddr: 0x800000, + }, + want: 0xF50000, + }, + { + name: "WRAM bank $80:1FFF", + args: args{ + busAddr: 0x801FFF, + }, + want: 0xF51FFF, + }, + { + name: "WRAM bank $9F:0000", + args: args{ + busAddr: 0x9F0000, + }, + want: 0xF50000, + }, + { + name: "WRAM bank $9F:1FFF", + args: args{ + busAddr: 0x9F1FFF, + }, + want: 0xF51FFF, + }, + { + name: "WRAM bank $A0:0000", + args: args{ + busAddr: 0xA00000, + }, + want: 0xF50000, + }, + { + name: "WRAM bank $A0:1FFF", + args: args{ + busAddr: 0xA01FFF, + }, + want: 0xF51FFF, + }, + { + name: "WRAM bank $BF:0000", + args: args{ + busAddr: 0xBF0000, + }, + want: 0xF50000, + }, + { + name: "WRAM bank $BF:1FFF", + args: args{ + busAddr: 0xBF1FFF, + }, + want: 0xF51FFF, + }, + // WRAM banks 7E-7F: + { + name: "WRAM bank $7E:0000", + args: args{ + busAddr: 0x7E0000, + }, + want: 0xF50000, + }, + { + name: "WRAM bank $7E:1FFF", + args: args{ + busAddr: 0x7E1FFF, + }, + want: 0xF51FFF, + }, + { + name: "WRAM bank $7E:2000", + args: args{ + busAddr: 0x7E2000, + }, + want: 0xF52000, + }, + { + name: "WRAM bank $7E:3FFF", + args: args{ + busAddr: 0x7E3FFF, + }, + want: 0xF53FFF, + }, + { + name: "WRAM bank $7E:FFFF", + args: args{ + busAddr: 0x7EFFFF, + }, + want: 0xF5FFFF, + }, + { + name: "WRAM bank $7F:0000", + args: args{ + busAddr: 0x7F0000, + }, + want: 0xF60000, + }, + { + name: "WRAM bank $7F:FFFF", + args: args{ + busAddr: 0x7FFFFF, + }, + want: 0xF6FFFF, + }, + // banks 00-7D: + { + name: "ROM bank $40:0000", + args: args{ + busAddr: 0x400000, + }, + want: 0x400000, + }, + { + name: "ROM bank $40:FFFF", + args: args{ + busAddr: 0x40FFFF, + }, + want: 0x40FFFF, + }, + { + name: "ROM bank $7D:0000", + args: args{ + busAddr: 0x7D0000, + }, + want: 0x7D0000, + }, + { + name: "ROM bank $7D:FFFF", + args: args{ + busAddr: 0x7DFFFF, + }, + want: 0x7DFFFF, + }, + { + name: "ROM bank $20:8000", + args: args{ + busAddr: 0x208000, + }, + want: 0x500000, + }, + { + name: "ROM bank $21:8000", + args: args{ + busAddr: 0x218000, + }, + want: 0x508000, + }, + // WRAM: + { + name: "WRAM bank $00:0000", + args: args{ + busAddr: 0x000000, + }, + want: 0xF50000, + }, + { + name: "WRAM bank $00:1FFF", + args: args{ + busAddr: 0x001FFF, + }, + want: 0xF51FFF, + }, + { + name: "WRAM bank $1F:0000", + args: args{ + busAddr: 0x1F0000, + }, + want: 0xF50000, + }, + { + name: "WRAM bank $1F:1FFF", + args: args{ + busAddr: 0x1F1FFF, + }, + want: 0xF51FFF, + }, + { + name: "WRAM bank $20:0000", + args: args{ + busAddr: 0x200000, + }, + want: 0xF50000, + }, + { + name: "WRAM bank $20:1FFF", + args: args{ + busAddr: 0x201FFF, + }, + want: 0xF51FFF, + }, + { + name: "WRAM bank $3F:0000", + args: args{ + busAddr: 0x3F0000, + }, + want: 0xF50000, + }, + { + name: "WRAM bank $3F:1FFF", + args: args{ + busAddr: 0x3F1FFF, + }, + want: 0xF51FFF, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if got := BusAddressToPak(tt.args.busAddr); got != tt.want { + t.Errorf("BusAddressToPak() = %v, want %v", got, tt.want) + } + }) + } +}