# Action 53 mapper/Reference implementations

(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)

These reference implementations of the PRG ROM bank formula in the Action 53 mapper (mapper 28) may be used to verify emulator or hardware implementations of this mapper.

## Python

```#!/usr/bin/env python3
from __future__ import print_function

bank_size_masks = [(2<<i)-1 for i in range(4)]  # 0x01, 0x03, 0x07, 0x0F

"""Calculate the 16K bank on A20-A14 for a given address.

in range 0x8000-0xFFFF
bank_mode -- last value written to \$80
outer_bank -- last value written to \$81
current_bank -- last value written to \$01

"""
cpu_a14 = (address >> 14) & 0x01
outer_bank = outer_bank << 1
bank_mode >>= 2  # discard mirroring bits
if (bank_mode ^ cpu_a14) & 0x03 == 0x02:  # in UNROM fixed bank?
bank_mode = 0  # if so, treat as NROM
if (bank_mode & 0x02) == 0:  # in 32K bank mode?
current_bank = (current_bank << 1) | cpu_a14

def test_with_bank_mode_size(bank_mode, outer_bank):
print("mode \$%02x, outer bank \$%02x" % (bank_mode, outer_bank))
out80 = [calc_prg_bank(0x8000, bank_mode, outer_bank, current_bank)
for current_bank in range(16)]
print("\$8000 banks:", " ".join("%02x" % i for i in out80))
outC0 = [calc_prg_bank(0xC000, bank_mode, outer_bank, current_bank)
for current_bank in range(16)]
print("\$C000 banks:", " ".join("%02x" % i for i in outC0))

for outer_bank in (0x00, 0x3C, 0x3F):
test_with_bank_mode_size(0x28, outer_bank)
for outer_bank in (0x00, 0x03, 0x3F):
test_with_bank_mode_size(0x2C, outer_bank)
for bank_mode in (0x00, 0x08, 0x0C, 0x10, 0x18, 0x1C,
0x20, 0x28, 0x2C, 0x30, 0x38, 0x3C):
test_with_bank_mode_size(bank_mode, 0x2A)
```

## 6502 assembly

This routine appears in the test ROMs "test28" and "Holy Mapperel".

```;;
; Determines what 16 KiB PRG ROM bank ought to be mapped into a given
; CPU address with a given set of \$80, \$81, \$00 values.
; For use in a test ROM that verifies mapper 28.
; @param A \$80 value
; @param X \$01 value
; @param Y \$81 value
; @param C CPU A14 value: clear for \$8000-\$BFFF, set for \$C000-\$FFFF
; @return PRG bank number in A
.proc calc_prg_bank
bank_mode = 0
outer_bank = 1
current_bank = 2
stx current_bank
sty outer_bank
rol outer_bank
lsr a  ; discard mirroring bits
lsr a
sta bank_mode

; If the mode is UxROM (10 = mapper 180, 11 = mapper 2), and bit 0
; of the mode matches CPU A14, then the read is within the fixed
; bank.  For such reads, the mapper acts in 32K (NROM) mode.
and #\$02
beq not_unrom
lda outer_bank
eor bank_mode
; If bit 0 of the eor result is false, there is a match, so
; fall through to the not-UNROM code.
and #\$01
bne have_current_bank
sta bank_mode

not_unrom:
; In 32K switched modes (NROM, CNROM, BNROM, AOROM),
; shift CPU A14 into the current bank
lda outer_bank
lsr a
rol current_bank

have_current_bank:
lda bank_mode
lsr a
lsr a
and #\$03
tax
lda current_bank
eor outer_bank