Action 53 mapper/Reference implementations

From NESdev Wiki
Revision as of 16:07, 14 October 2012 by Tepples (talk | contribs) (Created page with "These are reference implementations of the PRG ROM bank formula in the multicart mapper used for the Streemerz bundle ([[iNES Mapper 028...")
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to navigationJump to search

These are reference implementations of the PRG ROM bank formula in the multicart mapper used for the Streemerz bundle (mapper 28). They may be used to verify emulator or hardware implementations of this mapper.

Python

#!/usr/bin/env python

bank_size_masks = [(2<<i)-1 for i in range(4)]

def calc_prg_bank(address, bank_mode, outer_bank, current_bank):
    """Calculate the 16K bank on A20-A14 for a given address."""
    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
    bank_size_mask = bank_size_masks[(bank_mode >> 2) & 3]
    return ((current_bank ^ outer_bank) & bank_size_mask) ^ outer_bank

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

;;
; 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
  and bank_size_masks,x
  eor outer_bank
  rts
.endproc

.segment "RODATA"
bank_size_masks: .byt $01, $03, $07, $0F