Address Conversion

The same SNES address will correspond to a different PC address depending on the map mode of the ROM. This page lists the algorithms used to convert between SNES and PC addresses in different map modes.

All algorithms here are based on the source code of ASAR, a popular SNES assembler.

LoROM

PC to SNES:

in_WRAM := SNES & FE_0000₁₆ = 7E_0000₁₆
in_MISC := SNES & 70_8000₁₆ = 70_0000₁₆
in_SRAM := SNES & 40_8000₁₆ = 0

if not (in_WRAM or in_MISC or in_SRAM):
    PC := ((SNES & 7F_0000₁₆) >> 1) | (SNES & 7FFF₁₆)
else:
    invalid address

SNES to PC:

if PC < 40_0000₁₆:
    SNES := ((PC << 1) & 7F_0000₁₆) | (PC & 7FFF₁₆) | 80_8000₁₆
else:
    invalid address

HiROM

PC to SNES:

if PC < 40_0000₁₆:
    SNES := PC | C0_0000₁₆
else:
    invalid address

SNES to PC:

in_WRAM := SNES & FE_0000₁₆ = 7E_0000₁₆
in_MISC := SNES & 40_8000₁₆ = 0

if not (in_WRAM or in_MISC):
    PC := SNES & 3F_FFFF₁₆
else:
    invalid address

Ex LoROM

PC to SNES:

if PC < 80_0000₁₆:
    if PC & 40_0000₁₆ ≠ 0:
        A := PC - 40_0000₁₆
        M := 8000₁₆
    else:
        A := PC
        M := 808000₁₆
    SNES := ((A << 1) & 7F_0000₁₆) | (A & 7FFF₁₆) | M
else:
    invalid address

SNES to PC:

in_WRAM_SRAM  := SNES & F0_0000₁₆ = 70_0000₁₆
outside_LoROM := SNES & 40_8000₁₆ = 0

if not (in_WRAM_SRAM or outside_LoROM):
    PC := (((SNES & 7F_0000₁₆) >> 1) | (SNES & 7FFF₁₆))
    if SNES & 80_0000₁₆ ≠ 0:
        PC := PC + 40_0000₁₆
else:
    invalid address

Ex HiROM

PC to SNES:

if PC < 80_0000₁₆:
    if SNES & 40_0000₁₆ ≠ 0:
        PC := SNES
    else:
        PC := SNES | C0_0000₁₆
else:
    invalid address

SNES to PC:

in_WRAM := SNES & FE_0000₁₆ ≠ 7E_0000₁₆
in_MISC := SNES & 40_8000₁₆ ≠ 0

if not (in_WRAM or in_MISC):
    if SNES & 80_0000₁₆ ≠ 0:
        PC := (SNES & 3F_FFFF₁₆)
    else:
        PC := (SNES & 3F_FFFF₁₆) | 40_0000₁₆
else:
    invalid address

SFX ROM

PC to SNES:

if PC < 20_0000₁₆:
    SNES := ((PC << 1) & 7F_0000₁₆) | (PC & 7FFF₁₆) | 8000₁₆
else:
    invalid address

SNES to PC:

in_WRAM_SRAM_openbus := SNES & 60_0000₁₆ = 60_0000₁₆
in_MISC              := SNES & 40_8000₁₆ = 0
in_fastROM           := SNES & 80_0000₁₆ = 80_0000₁₆

if not (in_WRAM_SRAM_openbus or in_MISC or in_fastROM):
    if SNES & 40_0000₁₆ ≠ 0:
        PC = SNES & 3F_FFFF₁₆
    else:
        PC = ((SNES & 7F_0000₁₆) >> 1) | (SNES & 7FFF₁₆)
else:
    invalid address

SA1 ROM

PC to SNES:

if SA1_BANKS.contains(PC & 70_0000₁₆):
    BANK := SA1_BANKS.index_of(PC & 70_0000₁₆) << 21
    SNES := BANK | ((SNES & 0F_8000₁₆) << 1) | (SNES & 7FFF₁₆) | 8000₁₆
else:
    invalid address

SNES to PC:

if SNES & 40_8000₁₆ = 8000₁₆:
    B  := (addr & E0_0000₁₆) >> 21
    PC := SA1_BANKS[B] | ((addr & 1F_0000₁₆) >> 1) | (addr & 00_7FFF₁₆)
else if SNES & C0_0000₁₆ = C0_0000₁₆:
    B  := ((addr & 10_0000₁₆) >> 20) | ((addr & 20_0000₁₆) >> 19)
    PC := SA1_BANKS[B] | (addr & 0F_FFFF₁₆)
else:
    invalid address

Where:

SA1_BANKS[0] := 0 << 20
SA1_BANKS[1] := 1 << 20
SA1_BANKS[4] := 2 << 20
SA1_BANKS[5] := 3 << 20

SA1 banks 2, 3, 6, and 7 are not used.

Big SA1 ROM

PC to SNES:

if PC < 80_0000₁₆:
    if PC & 40_0000₁₆ = 40_0000₁₆:
        SNES := PC | C0_0000₁₆
    else:
        SNES := ((PC << 1) & 3F_0000₁₆) | (PC & 7FFF₁₆)
        if PC & 60_0000₁₆ = 20_0000₁₆:
            SNES := SNES | 8000₁₆
        else if PC & 60_0000₁₆ = 0:
            SNES := SNES | 80_8000₁₆
else:
    invalid address

SNES to PC:

in_HiROM := SNES & C0_0000₁₆ = C0_0000₁₆
in_LoROM := SNES & C0_0000₁₆ = either(0, 80_0000₁₆)

if in_HiROM:
    PC := (SNES & 3F_FFFF₁₆) | 40_0000₁₆
else if in_LoROM and SNES & 8000₁₆ ≠ 0:
    PC := ((SNES & 80_0000₁₆) >> 2) | 
          ((SNES & 3F_0000₁₆) >> 1) | (SNES & 7FFF₁₆)
else:
    invalid address