NromMapper.java

1
package com.rox.cartridge;
2
3
import com.rox.mem.RAM;
4
5
import static com.rox.ByteUtil.BYTE_MASK;
6
7
/**
8
 * iNES mapper 0 (NROM): PRG-ROM is fixed at {@code $8000-$FFFF} with no bank registers - a 16KB ROM
9
 * is mirrored into both halves of that window, a 32KB ROM fills it directly. Writes to {@code $8000+}
10
 * are no-ops (real NROM boards have nothing to switch). Always backed by 8KB of PRG-RAM at
11
 * {@code $6000-$7FFF} - not universal on real NROM boards, but needed here since that's exactly
12
 * where blargg's test ROMs report their pass/fail status.
13
 *
14
 * CHR is a single fixed 8KB bank, no banking registers to switch it (same "nothing to switch"
15
 * simplicity as PRG) - CHR-ROM if the ROM has any, else CHR-RAM (writable, for games that generate
16
 * their own tiles). Mirroring is whatever the iNES header says and never changes - NROM boards have
17
 * no register to override it, unlike MMC1.
18
 */
19
public final class NromMapper implements Mapper {
20
    private static final int PRG_RAM_SIZE = 0x2000;
21
    private static final int PRG_ROM_START_ADDRESS = 0x8000;
22
    private static final int SINGLE_BANK_SIZE = 0x4000;
23
    private static final int DOUBLE_BANK_SIZE = SINGLE_BANK_SIZE * 2;
24
    private static final int CHR_SIZE = 0x2000;
25
26
    private final byte[] prgRom;
27
    private final RAM prgRam = new RAM(PRG_RAM_SIZE, "PRG-RAM");
28
    private final ChrMemory chr;
29
    private final Mirroring mirroring;
30
31
    public NromMapper(final INesRom rom){
32
        this.prgRom = rom.prgRom();
33 2 1. <init> : negated conditional → KILLED
2. <init> : negated conditional → KILLED
        if (prgRom.length != SINGLE_BANK_SIZE && prgRom.length != DOUBLE_BANK_SIZE){
34
            throw new IllegalArgumentException(
35
                    "NROM expects 16KB or 32KB PRG-ROM, got " + prgRom.length + " bytes");
36
        }
37
        this.chr = ChrMemory.of(rom, CHR_SIZE);
38 1 1. <init> : negated conditional → KILLED
        this.mirroring = rom.isVerticalMirroring() ? Mirroring.VERTICAL : Mirroring.HORIZONTAL;
39
    }
40
41
    /**
42
     * Contract: only ever called with {@code address} in {@code $6000-$FFFF} (see class Javadoc).
43
     * PRG-ROM mirroring (16KB banks repeating to fill the 32KB window) falls out for free from
44
     * masking to {@code prgRom.length - 1} - both bank sizes are powers of two, same trick
45
     * {@link com.rox.mem.RAM} uses for its own address wraparound.
46
     */
47
    @Override
48
    public int read(final int address){
49 2 1. read : negated conditional → KILLED
2. read : changed conditional boundary → KILLED
        if (address >= PRG_ROM_START_ADDRESS){
50 4 1. read : Replaced bitwise AND with OR → KILLED
2. read : Replaced integer subtraction with addition → KILLED
3. read : replaced int return with 0 for com/rox/cartridge/NromMapper::read → KILLED
4. read : Replaced bitwise AND with OR → KILLED
            return prgRom[address & (prgRom.length - 1)] & BYTE_MASK;
51
        }
52 1 1. read : replaced int return with 0 for com/rox/cartridge/NromMapper::read → KILLED
        return prgRam.read(address);
53
    }
54
55
    /** Contract: only ever called with {@code address} in {@code $6000-$FFFF} (see class Javadoc). */
56
    @Override
57
    public void write(final int address, final int value){
58 2 1. write : negated conditional → KILLED
2. write : changed conditional boundary → KILLED
        if (address < PRG_ROM_START_ADDRESS){
59 1 1. write : removed call to com/rox/mem/RAM::write → KILLED
            prgRam.write(address, value);
60
        }
61
    }
62
63
    @Override
64
    public int readChr(final int address){
65 2 1. readChr : Replaced bitwise AND with OR → KILLED
2. readChr : replaced int return with 0 for com/rox/cartridge/NromMapper::readChr → KILLED
        return chr.read(address & (CHR_SIZE - 1));
66
    }
67
68
    /** No-op on CHR-ROM boards - real hardware has nowhere to write CHR-ROM writes to. */
69
    @Override
70
    public void writeChr(final int address, final int value){
71 2 1. writeChr : removed call to com/rox/cartridge/ChrMemory::write → KILLED
2. writeChr : Replaced bitwise AND with OR → KILLED
        chr.write(address & (CHR_SIZE - 1), value);
72
    }
73
74
    @Override
75
    public Mirroring nametableMirroring(){
76 1 1. nametableMirroring : replaced return value with null for com/rox/cartridge/NromMapper::nametableMirroring → KILLED
        return mirroring;
77
    }
78
79
    @Override
80
    public int[] prgRam(){
81 1 1. prgRam : replaced return value with null for com/rox/cartridge/NromMapper::prgRam → KILLED
        return prgRam.snapshot();
82
    }
83
84
    @Override
85
    public void restorePrgRam(final int[] prgRam){
86 1 1. restorePrgRam : removed call to com/rox/mem/RAM::restore → KILLED
        this.prgRam.restore(prgRam);
87
    }
88
89
    @Override
90
    public MapperSnapshot snapshot(){
91 1 1. snapshot : replaced return value with null for com/rox/cartridge/NromMapper::snapshot → KILLED
        return new NromMapperSnapshot(prgRam.snapshot(), chr.snapshot());
92
    }
93
94
    @Override
95
    public void checkRestorable(final MapperSnapshot snapshot){
96
        final NromMapperSnapshot nrom = SnapshotArrays.expect(snapshot, NromMapperSnapshot.class);
97 1 1. checkRestorable : removed call to com/rox/mem/RAM::checkRestorable → KILLED
        prgRam.checkRestorable(nrom.prgRam());
98 1 1. checkRestorable : removed call to com/rox/cartridge/ChrMemory::checkRestorable → KILLED
        chr.checkRestorable(nrom.chrRam());
99
    }
100
101
    @Override
102
    public void restore(final MapperSnapshot snapshot){
103 1 1. restore : removed call to com/rox/cartridge/NromMapper::checkRestorable → KILLED
        checkRestorable(snapshot);
104
        final NromMapperSnapshot nrom = (NromMapperSnapshot) snapshot;
105 1 1. restore : removed call to com/rox/mem/RAM::restore → KILLED
        prgRam.restore(nrom.prgRam());
106 1 1. restore : removed call to com/rox/cartridge/ChrMemory::restore → KILLED
        chr.restore(nrom.chrRam());
107
    }
108
}

Mutations

33

1.1
Location : <init>
Killed by : com.rox.cartridge.NromMapperTest.[engine:junit-jupiter]/[class:com.rox.cartridge.NromMapperTest]/[method:rejectsPrgRomThatIsNeither16Nor32KbBanks()]
negated conditional → KILLED

2.2
Location : <init>
Killed by : com.rox.cartridge.NromMapperTest.[engine:junit-jupiter]/[class:com.rox.cartridge.NromMapperTest]/[method:rejectsPrgRomThatIsNeither16Nor32KbBanks()]
negated conditional → KILLED

38

1.1
Location : <init>
Killed by : com.rox.cartridge.NromMapperTest.[engine:junit-jupiter]/[class:com.rox.cartridge.NromMapperTest]/[method:mirroringReflectsTheHeaderBitAtConstructionTime()]
negated conditional → KILLED

49

1.1
Location : read
Killed by : com.rox.cartridge.NromMapperTest.[engine:junit-jupiter]/[class:com.rox.cartridge.NromMapperTest]/[method:sixteenKbRomIsMirroredIntoBothHalvesOfTheWindow()]
negated conditional → KILLED

2.2
Location : read
Killed by : com.rox.cartridge.NromMapperTest.[engine:junit-jupiter]/[class:com.rox.cartridge.NromMapperTest]/[method:thirtyTwoKbRomFillsTheWholeWindowWithoutMirroring()]
changed conditional boundary → KILLED

50

1.1
Location : read
Killed by : com.rox.cartridge.NromMapperTest.[engine:junit-jupiter]/[class:com.rox.cartridge.NromMapperTest]/[method:sixteenKbRomIsMirroredIntoBothHalvesOfTheWindow()]
Replaced bitwise AND with OR → KILLED

2.2
Location : read
Killed by : com.rox.cartridge.NromMapperTest.[engine:junit-jupiter]/[class:com.rox.cartridge.NromMapperTest]/[method:sixteenKbRomIsMirroredIntoBothHalvesOfTheWindow()]
Replaced integer subtraction with addition → KILLED

3.3
Location : read
Killed by : com.rox.cartridge.NromMapperTest.[engine:junit-jupiter]/[class:com.rox.cartridge.NromMapperTest]/[method:sixteenKbRomIsMirroredIntoBothHalvesOfTheWindow()]
replaced int return with 0 for com/rox/cartridge/NromMapper::read → KILLED

4.4
Location : read
Killed by : com.rox.cartridge.NromMapperTest.[engine:junit-jupiter]/[class:com.rox.cartridge.NromMapperTest]/[method:sixteenKbRomIsMirroredIntoBothHalvesOfTheWindow()]
Replaced bitwise AND with OR → KILLED

52

1.1
Location : read
Killed by : com.rox.cartridge.NromMapperTest.[engine:junit-jupiter]/[class:com.rox.cartridge.NromMapperTest]/[method:writeMasksValueTo8Bits()]
replaced int return with 0 for com/rox/cartridge/NromMapper::read → KILLED

58

1.1
Location : write
Killed by : com.rox.cartridge.NromMapperTest.[engine:junit-jupiter]/[class:com.rox.cartridge.NromMapperTest]/[method:prgRamIsADefensiveCopyNotALiveView()]
negated conditional → KILLED

2.2
Location : write
Killed by : com.rox.cartridge.NromMapperTest.[engine:junit-jupiter]/[class:com.rox.cartridge.NromMapperTest]/[method:writesToPrgRomAreNoOps()]
changed conditional boundary → KILLED

59

1.1
Location : write
Killed by : com.rox.cartridge.NromMapperTest.[engine:junit-jupiter]/[class:com.rox.cartridge.NromMapperTest]/[method:prgRamIsADefensiveCopyNotALiveView()]
removed call to com/rox/mem/RAM::write → KILLED

65

1.1
Location : readChr
Killed by : com.rox.cartridge.NromMapperTest.[engine:junit-jupiter]/[class:com.rox.cartridge.NromMapperTest]/[method:noChrBanksMeansWritableChrRam()]
Replaced bitwise AND with OR → KILLED

2.2
Location : readChr
Killed by : com.rox.cartridge.NromMapperTest.[engine:junit-jupiter]/[class:com.rox.cartridge.NromMapperTest]/[method:noChrBanksMeansWritableChrRam()]
replaced int return with 0 for com/rox/cartridge/NromMapper::readChr → KILLED

71

1.1
Location : writeChr
Killed by : com.rox.cartridge.NromMapperTest.[engine:junit-jupiter]/[class:com.rox.cartridge.NromMapperTest]/[method:noChrBanksMeansWritableChrRam()]
removed call to com/rox/cartridge/ChrMemory::write → KILLED

2.2
Location : writeChr
Killed by : com.rox.cartridge.NromMapperTest.[engine:junit-jupiter]/[class:com.rox.cartridge.NromMapperTest]/[method:noChrBanksMeansWritableChrRam()]
Replaced bitwise AND with OR → KILLED

76

1.1
Location : nametableMirroring
Killed by : com.rox.cartridge.NromMapperTest.[engine:junit-jupiter]/[class:com.rox.cartridge.NromMapperTest]/[method:mirroringReflectsTheHeaderBitAtConstructionTime()]
replaced return value with null for com/rox/cartridge/NromMapper::nametableMirroring → KILLED

81

1.1
Location : prgRam
Killed by : com.rox.cartridge.NromMapperTest.[engine:junit-jupiter]/[class:com.rox.cartridge.NromMapperTest]/[method:prgRamIsADefensiveCopyNotALiveView()]
replaced return value with null for com/rox/cartridge/NromMapper::prgRam → KILLED

86

1.1
Location : restorePrgRam
Killed by : com.rox.cartridge.NromMapperTest.[engine:junit-jupiter]/[class:com.rox.cartridge.NromMapperTest]/[method:restorePrgRamRejectsTheWrongLength()]
removed call to com/rox/mem/RAM::restore → KILLED

91

1.1
Location : snapshot
Killed by : com.rox.cartridge.MapperSnapshotTest.[engine:junit-jupiter]/[class:com.rox.cartridge.MapperSnapshotTest]/[method:snapshotIsACopyNotALiveView()]
replaced return value with null for com/rox/cartridge/NromMapper::snapshot → KILLED

97

1.1
Location : checkRestorable
Killed by : com.rox.cartridge.MapperSnapshotTest.[engine:junit-jupiter]/[class:com.rox.cartridge.MapperSnapshotTest]/[test-template:checkRestorableRejectsWhicheverArrayIsWrong(java.lang.String, java.lang.String)]/[test-template-invocation:#1]
removed call to com/rox/mem/RAM::checkRestorable → KILLED

98

1.1
Location : checkRestorable
Killed by : com.rox.cartridge.MapperSnapshotTest.[engine:junit-jupiter]/[class:com.rox.cartridge.MapperSnapshotTest]/[method:restoreRejectsAChrRomSnapshotOnAChrRamBoard()]
removed call to com/rox/cartridge/ChrMemory::checkRestorable → KILLED

103

1.1
Location : restore
Killed by : com.rox.cartridge.MapperSnapshotTest.[engine:junit-jupiter]/[class:com.rox.cartridge.MapperSnapshotTest]/[method:restoreRejectsAChrRomSnapshotOnAChrRamBoard()]
removed call to com/rox/cartridge/NromMapper::checkRestorable → KILLED

105

1.1
Location : restore
Killed by : com.rox.cartridge.MapperSnapshotTest.[engine:junit-jupiter]/[class:com.rox.cartridge.MapperSnapshotTest]/[method:nromRoundTripsItsRam()]
removed call to com/rox/mem/RAM::restore → KILLED

106

1.1
Location : restore
Killed by : com.rox.cartridge.MapperSnapshotTest.[engine:junit-jupiter]/[class:com.rox.cartridge.MapperSnapshotTest]/[method:nromRoundTripsItsRam()]
removed call to com/rox/cartridge/ChrMemory::restore → KILLED

Active mutators

Tests examined


Report generated by PIT 1.22.1