PPU.java

1
package com.rox.ppu;
2
3
import com.rox.ByteUtil;
4
import com.rox.cartridge.Cartridge;
5
import com.rox.cartridge.Mirroring;
6
import com.rox.clock.ClockWatcher;
7
import com.rox.mem.OamDmaBus;
8
9
import static com.rox.ByteUtil.*;
10
import static com.rox.ByteUtil.BYTE_MASK;
11
12
/**
13
 * Headless NES PPU: correct vblank/NMI timing, full {@code $0000-$3FFF} PPU address space wiring
14
 * (CHR pattern tables via the cartridge, mirrored nametable RAM, palette RAM), the "loopy" internal
15
 * scroll/address registers, OAM DMA, and background + sprite rendering to a {@link #framebuffer()} of
16
 * raw palette indices (0-63) - {@link #rgbFramebuffer()} converts those through {@link NesPalette} for
17
 * actual display. Registers repeat every 8 bytes through {@code $2000-$3FFF}.
18
 *
19
 * Runs at 3 dots per CPU cycle (NTSC), 341 dots/scanline, 262 scanlines/frame. Vblank starts at
20
 * scanline 241 dot 1 and clears at the start of the pre-render scanline (261, dot 1) - matching real
21
 * hardware, this happens automatically every frame regardless of whether {@code $2002} is ever read.
22
 * NMI is modeled as a real level (vblank flag AND the control register's NMI-enable bit) with edge
23
 * detection, not a one-shot check at vblank's start: this also reproduces the documented hardware
24
 * quirk where enabling NMI while the vblank flag is already set fires an NMI immediately. Callers
25
 * drive the CPU's actual NMI line from {@link #consumeNmiEdge()}, one-shot per rising edge (mirrors
26
 * {@code MOS6502}'s own {@code signalNMI()}/{@code consumeNMI()} edge-latch pattern) - see how
27
 * {@code NES.java} wires this in exactly like the existing APU-IRQ listener.
28
 *
29
 * The internal current/temporary VRAM address, fine-X-scroll and write-toggle fields follow nesdev's
30
 * standard "loopy" model (traditionally named {@code v}/{@code t}/{@code x}/{@code w} there):
31
 * {@link #currentVramAddress} (used for {@code $2007} access) and {@link #temporaryVramAddress}
32
 * (staged by {@code $2005}/{@code $2006} until latched into {@code currentVramAddress}) are both
33
 * conceptually 15 bits laid out as {@code 0yyy NNYY YYYX XXXX} (fine Y, nametable select, coarse Y,
34
 * coarse X); {@link #fineXScroll} is 3 bits; {@link #writeToggle} is shared by
35
 * {@code $2005}/{@code $2006}, reset by a {@code $2002} read. Besides the register-level bit
36
 * manipulation ({@code $2000} nametable-select bits, {@code $2005} coarse/fine split, {@code $2006}
37
 * address latching), {@code currentVramAddress} also drives the background rendering pipeline's own
38
 * rendering-time-only updates: coarse-X increment during fetches, Y increment at dot 256, and the
39
 * dot-257/280-304 horizontal/vertical copies from {@code temporaryVramAddress} - see
40
 * {@link #backgroundStep()}.
41
 *
42
 * Simplifications: no odd-frame dot skip (341*262 isn't evenly divisible by 3, so the exact CPU-cycle
43
 * offset of vblank drifts by fractions of a cycle frame to frame - harmless here, only the dot
44
 * position within a frame matters). Four-screen nametable mirroring isn't modeled (see
45
 * {@link Mirroring}). OAM DMA always stalls the CPU a fixed 514 cycles, not real hardware's 513 (even
46
 * start cycle) or 514 (odd) - no total-cycle counter exists anywhere in the CPU to detect that parity,
47
 * and the 1-cycle difference doesn't affect correctness, only real-hardware-exact timing.
48
 *
49
 * Sprite pipeline simplifications: real hardware spreads secondary-OAM evaluation and sprite pattern
50
 * fetching across dots 65-256 and 257-320 respectively; both are collapsed here into a single step (at
51
 * dots 65 and 257) since nothing outside the PPU can observe mid-evaluation/mid-fetch state - the
52
 * resulting secondary OAM and fetched pattern bytes are byte-for-byte identical to real hardware's by
53
 * the time the next scanline starts. <b>One documented exception</b>: {@link com.rox.cartridge.Mmc3Mapper}
54
 * treats every {@link com.rox.cartridge.Mapper#readChr} call as directly observable (it clocks its IRQ
55
 * counter off the PPU address bus's A12 line), so collapsing dots 257-320's per-slot fetches into one
56
 * dot-257 step is only timing-transparent to it when at most one A12 edge would occur across those real
57
 * dots anyway - true for the common case, not for 8x16 sprites mixing pattern-table halves across
58
 * sprites; see {@link com.rox.cartridge.Mmc3Mapper}'s own class doc "Known limitation" note. Sprite
59
 * overflow uses a simple "found more than 8 sprites in range"
60
 * count, not real hardware's well-known buggy diagonal-read overflow detection (see nesdev's "Sprite
61
 * overflow bug") - only the obscure false-positive/false-negative edge cases differ, not correct
62
 * rendering. OAMADDR's glitchy behaviour during evaluation (real hardware corrupts low OAM entries if
63
 * OAMADDR isn't 0 at the start of a scanline) isn't modeled.
64
 */
65
public class PPU implements ClockWatcher, OamDmaBus {
66
    public static final int FRAMEBUFFER_WIDTH = 256;
67
    public static final int FRAMEBUFFER_HEIGHT = 240;
68
69
    /**
70
     * Where things fall on the 341-dot/scanline, 262-scanline/frame grid: scanlines 0-239 are visible,
71
     * 240 is post-render (idle), 241-260 are vertical blank, 261 is the pre-render scanline.
72
     * {@code DOTS_PER_SCANLINE}/{@code SCANLINES_PER_FRAME} are public since the debug viewer's
73
     * {@code BeamPositionPanel} draws against them directly; everything else here is {@code PPU}-internal.
74
     */
75
    public static final class FrameTiming {
76
        public static final int DOTS_PER_SCANLINE = 341;
77
        public static final int SCANLINES_PER_FRAME = 262;
78
        static final int DOTS_PER_CPU_CYCLE = 3;
79
        static final int VBLANK_START_SCANLINE = 241;
80
        static final int VBLANK_END_SCANLINE = 261;
81
        static final int VBLANK_EDGE_DOT = 1;
82
        static final int VISIBLE_SCANLINE_MAX = 239;
83
84
        //341 dots/scanline isn't a multiple of the 3 dots/CPU-cycle rate, so the target dot doesn't
85
        //always land on a tick boundary - round up (ceiling division) to the tick whose 3-dot span
86
        //contains it. advanceDot() itself checks after every individual dot, not just per tick(), so
87
        //this only matters for computing these two "how many ticks until X" constants, not correctness.
88
        /** CPU ticks from power-on/reset until vblank first starts - exact, useful for tests. */
89
        static final int TICKS_UNTIL_VBLANK_START =
90
                ceilingDivide(VBLANK_START_SCANLINE * DOTS_PER_SCANLINE + VBLANK_EDGE_DOT, DOTS_PER_CPU_CYCLE);
91
        /** CPU ticks from power-on/reset until vblank first clears (pre-render scanline). */
92
        static final int TICKS_UNTIL_VBLANK_END =
93
                ceilingDivide(VBLANK_END_SCANLINE * DOTS_PER_SCANLINE + VBLANK_EDGE_DOT, DOTS_PER_CPU_CYCLE);
94
95
        private static int ceilingDivide(final int numerator, final int denominator){
96
            return (numerator + denominator - 1) / denominator;
97
        }
98
99
        private FrameTiming(){
100
        }
101
    }
102
103
    /** {@code $2000-$2007}'s CPU-bus offsets - registers repeat every 8 bytes through {@code $2000-$3FFF}. */
104
    private static final class RegisterAddress {
105
        static final int MASK = 0x07;
106
        static final int PPUCTRL = 0x00;
107
        static final int PPUMASK = 0x01;
108
        static final int PPUSTATUS = 0x02;
109
        static final int OAMADDR = 0x03;
110
        static final int OAMDATA = 0x04;
111
        static final int PPUSCROLL = 0x05;
112
        static final int PPUADDR = 0x06;
113
        static final int PPUDATA = 0x07;
114
115
        private RegisterAddress(){
116
        }
117
    }
118
119
    private static final int VBLANK_STATUS_BIT = 0x80;
120
121
    private static final int OAM_SIZE = 0x100;
122
    private static final int OAM_ADDRESS_MASK = 0xFF;
123
    private static final int VRAM_ADDRESS_MASK = 0x3FFF;
124
    private static final int LOOPY_REGISTER_MASK = 0x7FFF;
125
    private static final int ADDRESS_HIGH_BYTE_SHIFT = 8;
126
127
    private static final int CHR_END_ADDRESS = 0x2000; //exclusive - $0000-$1FFF
128
    private static final int PALETTE_START_ADDRESS = 0x3F00; //inclusive - $3F00-$3FFF
129
    private static final int NAMETABLE_SIZE = 0x800; //2KB physical nametable RAM
130
    private static final int NAMETABLE_OFFSET_MASK = 0x3FF; //1KB per logical nametable
131
    private static final int NAMETABLE_TABLE_SHIFT = 10;
132
    private static final int NAMETABLE_TABLE_MASK = 0x03;
133
    private static final int PALETTE_SIZE = 0x20;
134
    private static final int PALETTE_INDEX_MASK = 0x1F;
135
    private static final int PALETTE_BACKDROP_MIRROR_BIT = 0x10;
136
137
    //t/v bit layout: 0yyy NNYY YYYX XXXX (fine Y | nametable select | coarse Y | coarse X)
138
    private static final int COARSE_X_MASK = 0x1F;
139
    private static final int COARSE_Y_SHIFT = 5;
140
    private static final int COARSE_Y_MASK = 0x1F;
141
    private static final int NAMETABLE_SELECT_SHIFT = 10;
142
    private static final int NAMETABLE_SELECT_MASK = 0x03;
143
    private static final int FINE_Y_SHIFT = 12;
144
    private static final int FINE_Y_MASK = 0x07;
145
    private static final int FINE_X_MASK = 0x07;
146
    private static final int COARSE_X_CLEAR_MASK = ~COARSE_X_MASK & LOOPY_REGISTER_MASK;
147
    private static final int COARSE_Y_CLEAR_MASK = ~(COARSE_Y_MASK << COARSE_Y_SHIFT) & LOOPY_REGISTER_MASK;
148
    private static final int NAMETABLE_SELECT_CLEAR_MASK = ~(NAMETABLE_SELECT_MASK << NAMETABLE_SELECT_SHIFT) & LOOPY_REGISTER_MASK;
149
    private static final int FINE_Y_CLEAR_MASK = ~(FINE_Y_MASK << FINE_Y_SHIFT) & LOOPY_REGISTER_MASK;
150
    private static final int ADDRESS_HIGH_BYTE_MASK = 0x3F;
151
    private static final int ADDRESS_HIGH_BYTE_CLEAR_MASK = 0x00FF;
152
    private static final int ADDRESS_LOW_BYTE_CLEAR_MASK = 0x7F00;
153
154
    private static final int OAM_DMA_STALL_CYCLES = 514;
155
156
    //background rendering pipeline (nesdev's standard 8-dot tile-fetch cycle + shift registers),
157
    //verified dot-for-dot against nesdev's PPU_scrolling/PPU_rendering/PPU_palettes wiki pages
158
    private static final int TILE_FETCH_GROUP_DOTS = 8;
159
    private static final int MAIN_FETCH_REGION_END_DOT = 256; //dots 1-256
160
    private static final int HORIZONTAL_COPY_DOT = 257;
161
    private static final int PREFETCH_REGION_START_DOT = 321;
162
    private static final int PREFETCH_REGION_END_DOT = 336; //dots 321-336: next scanline's first 2 tiles
163
    private static final int PREFETCH_RELOAD_DOT = 337; //reloads the 2nd prefetched tile's data
164
    private static final int VERTICAL_COPY_START_DOT = 280;
165
    private static final int VERTICAL_COPY_END_DOT = 304; //pre-render only, dots 280-304 inclusive
166
167
    private static final int TILE_BYTES = 16; //8-byte low bitplane + 8-byte high bitplane
168
    private static final int PATTERN_HIGH_PLANE_OFFSET = 8;
169
170
    private static final int SHIFT_REGISTER_MASK = 0xFFFF;
171
    private static final int SHIFT_REGISTER_LOW_BYTE_CLEAR_MASK = 0xFF00;
172
    private static final int PIXEL_MUX_MSB = 0x8000;
173
174
    private static final int NAMETABLE_BASE_ADDRESS = 0x2000;
175
    private static final int NAMETABLE_FETCH_ADDRESS_MASK = 0x0FFF;
176
    private static final int ATTRIBUTE_BASE_ADDRESS = 0x23C0;
177
    private static final int ATTRIBUTE_NAMETABLE_MASK = 0x0C00;
178
    private static final int ATTRIBUTE_COARSE_Y_SHIFT_IN_ADDRESS = 4;
179
    private static final int ATTRIBUTE_COARSE_Y_ADDRESS_MASK = 0x38;
180
    private static final int ATTRIBUTE_COARSE_X_SHIFT_IN_ADDRESS = 2;
181
    private static final int ATTRIBUTE_COARSE_X_ADDRESS_MASK = 0x07;
182
    private static final int ATTRIBUTE_QUADRANT_BIT = 0x02;
183
    private static final int ATTRIBUTE_GROUP_MASK = 0x03;
184
185
    private static final int COARSE_X_MAX = 31; //wraps to 0 + toggles the nametable-X bit
186
    private static final int NAMETABLE_X_TOGGLE_BIT = 1 << NAMETABLE_SELECT_SHIFT; //bit 10 = 0x0400
187
    private static final int NAMETABLE_Y_TOGGLE_BIT = 1 << (NAMETABLE_SELECT_SHIFT + 1); //bit 11 = 0x0800
188
    private static final int FINE_Y_FULL_MASK = FINE_Y_MASK << FINE_Y_SHIFT; //0x7000
189
    private static final int COARSE_Y_WRAP_WITH_TOGGLE = 29; //last real row of tiles
190
    private static final int COARSE_Y_WRAP_WITHOUT_TOGGLE = 31; //attribute-table rows, no nametable toggle
191
    private static final int HORIZONTAL_COPY_MASK = COARSE_X_MASK | NAMETABLE_X_TOGGLE_BIT; //0x041F
192
    private static final int VERTICAL_COPY_MASK = FINE_Y_FULL_MASK | NAMETABLE_Y_TOGGLE_BIT
193
            | (COARSE_Y_MASK << COARSE_Y_SHIFT); //0x7BE0
194
195
    private static final int PALETTE_COLOR_MASK = 0x3F; //6-bit NES master-palette index (0-63)
196
197
    //sprite rendering pipeline (nesdev's standard OAM evaluation + pattern fetch + priority mux) - see
198
    //the class javadoc's "Sprite pipeline simplifications" paragraph for how this collapses real
199
    //hardware's multi-dot evaluation/fetch windows into single steps.
200
    private static final int OAM_SPRITE_COUNT = 64;
201
    private static final int OAM_BYTES_PER_SPRITE = 4;
202
    private static final int MAX_SPRITES_PER_SCANLINE = 8;
203
    private static final int SPRITE_HEIGHT_SHORT = 8;
204
    private static final int SPRITE_HEIGHT_TALL = 16;
205
    private static final int SPRITE_EVALUATION_DOT = 65;
206
    private static final int TALL_SPRITE_PATTERN_TABLE_SIZE = 0x1000;
207
    private static final int SPRITE_PALETTE_MASK = 0x03;
208
    private static final int SPRITE_PRIORITY_BEHIND_BACKGROUND_BIT = 0x20;
209
    private static final int SPRITE_FLIP_HORIZONTAL_BIT = 0x40;
210
    private static final int SPRITE_FLIP_VERTICAL_BIT = 0x80;
211
    private static final int SPRITE_PALETTE_RAM_OFFSET = 0x10; //$3F10-$3F1F vs background's $3F00-$3F0F
212
    private static final int SPRITE_ZERO_HIT_EXCLUDED_X = 255; //real hardware never sets the hit flag here
213
    private static final int SPRITE_ZERO_HIT_STATUS_BIT = 0x40;
214
    private static final int SPRITE_OVERFLOW_STATUS_BIT = 0x20;
215
    //real hardware's secondary-OAM-clear phase (dots 1-64) fills every byte with $FF; an unused sprite
216
    //slot's dummy pattern fetch (see fetchSpritesForNextScanline()) reads this same tile index
217
    private static final int DUMMY_SPRITE_TILE_INDEX = 0xFF;
218
219
    private final Cartridge cartridge;
220
221
    private final int[] oam = new int[OAM_SIZE];
222
    private final int[] nametableRam = new int[NAMETABLE_SIZE];
223
    private final int[] paletteRam = new int[PALETTE_SIZE];
224
225
    /**  a unit of time in which we advance by exactly one pixel-column's worth of work, whether or not that pixel is currently visible on screen. */
226
    private int dot;
227
    /** 341 dots, 256 of which are visible pixels */
228
    private int scanline;
229
230
    private boolean vblankFlag;
231
    private boolean previousNmiLine;
232
    private boolean nmiEdgePending;
233
234
    private PPUControlRegister controlRegister = new PPUControlRegister(0x0);
235
    private PPUMaskRegister maskRegister = new PPUMaskRegister(0x0);
236
    private int oamAddress;
237
238
    private boolean writeToggle; //shared $2005/$2006 write toggle
239
    private int temporaryVramAddress; //staged by $2005/$2006 until latched into currentVramAddress
240
    private int currentVramAddress; //used for $2007 access
241
    private int fineXScroll; //3 bits
242
    private int readBuffer; //$2007's one-read-of-latency buffer for non-palette addresses
243
244
    private boolean oamDmaPending;
245
246
    /** One raw palette-RAM index (0-63) per pixel - {@link #rgbFramebuffer()} converts these to real colour. */
247
    private final int[] framebuffer = new int[FRAMEBUFFER_WIDTH * FRAMEBUFFER_HEIGHT];
248
    private boolean frameReady;
249
250
    //two tiles' worth of pattern/attribute data, shifted left 1 bit per dot; fineXScroll selects
251
    //which bit each pixel is drawn from (see drawPixel())
252
    private int bgPatternShiftLow;
253
    private int bgPatternShiftHigh;
254
    private int bgAttributeShiftLow;
255
    private int bgAttributeShiftHigh;
256
    //latches for the tile currently being fetched (2 tiles ahead of what's being drawn), folded
257
    //into the shift registers' low byte by reloadShiftRegisters()
258
    private int nextTileId;
259
    private int nextTilePaletteGroup; //2 bits (0-3)
260
    private int nextPatternLowByte;
261
    private int nextPatternHighByte;
262
263
    //secondary OAM for the upcoming scanline (up to 8 sprites x 4 bytes), rebuilt every scanline by
264
    //evaluateSpritesForNextScanline()
265
    private final int[] secondaryOam = new int[MAX_SPRITES_PER_SCANLINE * OAM_BYTES_PER_SPRITE];
266
    private int secondaryOamCount;
267
    private int secondaryOamSpriteZeroSlot = -1; //-1 if OAM sprite 0 isn't in range this scanline
268
    private boolean spriteOverflow;
269
    private boolean spriteZeroHitFlag;
270
271
    //per-slot rendering state fetchSpritesForNextScanline() loaded for the *current* scanline's active
272
    //sprites - pattern bytes already have horizontal flip applied, so drawPixel() never needs to know
273
    //about flip at all
274
    private final int[] spritePatternLowByte = new int[MAX_SPRITES_PER_SCANLINE];
275
    private final int[] spritePatternHighByte = new int[MAX_SPRITES_PER_SCANLINE];
276
    private final int[] spriteAttributes = new int[MAX_SPRITES_PER_SCANLINE];
277
    private final int[] spriteXPosition = new int[MAX_SPRITES_PER_SCANLINE];
278
    private final boolean[] spriteIsZero = new boolean[MAX_SPRITES_PER_SCANLINE];
279
    private int activeSpriteCount;
280
281
    public PPU(final Cartridge cartridge){
282
        this.cartridge = cartridge;
283
    }
284
285
    /** CPU-cycle clock: the PPU itself runs at 3x this rate (once per dot, 3 dots per CPU cycle). */
286
    @Override
287
    public void tick(){
288 2 1. tick : changed conditional boundary → KILLED
2. tick : negated conditional → KILLED
        for (int i = 0; i < FrameTiming.DOTS_PER_CPU_CYCLE; i++){
289 1 1. tick : removed call to com/rox/ppu/PPU::advanceDot → KILLED
            advanceDot();
290
        }
291
    }
292
293
    private void advanceDot(){
294 1 1. advanceDot : Replaced integer addition with subtraction → KILLED
        dot++;
295 2 1. advanceDot : negated conditional → KILLED
2. advanceDot : changed conditional boundary → KILLED
        if (dot >= FrameTiming.DOTS_PER_SCANLINE){
296
            dot = 0;
297 1 1. advanceDot : Replaced integer addition with subtraction → KILLED
            scanline++;
298 2 1. advanceDot : negated conditional → KILLED
2. advanceDot : changed conditional boundary → KILLED
            if (scanline >= FrameTiming.SCANLINES_PER_FRAME){
299
                scanline = 0;
300
            }
301
        }
302 2 1. advanceDot : negated conditional → KILLED
2. advanceDot : negated conditional → KILLED
        if (scanline == FrameTiming.VBLANK_START_SCANLINE && dot == FrameTiming.VBLANK_EDGE_DOT){
303 1 1. advanceDot : removed call to com/rox/ppu/PPU::setVblankFlag → KILLED
            setVblankFlag(true);
304
            frameReady = true;
305 2 1. advanceDot : negated conditional → SURVIVED
2. advanceDot : negated conditional → SURVIVED
        } else if (scanline == FrameTiming.VBLANK_END_SCANLINE && dot == FrameTiming.VBLANK_EDGE_DOT){
306 1 1. advanceDot : removed call to com/rox/ppu/PPU::setVblankFlag → KILLED
            setVblankFlag(false);
307
            spriteOverflow = false;
308
            spriteZeroHitFlag = false;
309
        }
310 1 1. advanceDot : removed call to com/rox/ppu/PPU::backgroundStep → KILLED
        backgroundStep();
311 1 1. advanceDot : removed call to com/rox/ppu/PPU::spriteStep → KILLED
        spriteStep();
312
    }
313
314
    /** True exactly once per frame (set at scanline 241 dot 1) - mirrors {@link #consumeNmiEdge()}'s one-shot pattern. */
315
    public boolean consumeFrameReady(){
316 1 1. consumeFrameReady : negated conditional → KILLED
        if (frameReady){
317
            frameReady = false;
318 1 1. consumeFrameReady : replaced boolean return with false for com/rox/ppu/PPU::consumeFrameReady → KILLED
            return true;
319
        }
320 1 1. consumeFrameReady : replaced boolean return with true for com/rox/ppu/PPU::consumeFrameReady → KILLED
        return false;
321
    }
322
323
    /**
324
     * Runs on every dot of every visible (0-239) and pre-render (261) scanline. A pixel is drawn on
325
     * every dot 1-256 of a visible scanline regardless of whether rendering is enabled (falling back to
326
     * the backdrop colour when it isn't); the fetch/shift/scroll machinery below that only runs when
327
     * rendering is enabled - real hardware freezes the v register entirely otherwise.
328
     *
329
     * <p>The shift registers shift one dot <em>later</em> than the fetch switch's own dot range in each
330
     * region - dots 2-257 (not 1-256) and 322-337 (not 321-336) - and that shift happens <em>before</em>
331
     * this dot's pixel is drawn, not after: dot 1 draws directly from whatever the previous scanline's
332
     * prefetch already left sitting in the registers, with no shift of its own first. Getting either of
333
     * those backwards (shifting on the same 1-256/321-336 range the fetch switch uses, or drawing before
334
     * shifting) is a real, easy-to-make off-by-one - it shows up as the whole background shifted one
335
     * pixel to the right - caught here by simulating the exact algorithm against known CHR/nametable
336
     * fixtures before trusting it, not just by re-reading nesdev's timing diagram more carefully.
337
     */
338
    private void backgroundStep(){
339 3 1. backgroundStep : changed conditional boundary → KILLED
2. backgroundStep : negated conditional → KILLED
3. backgroundStep : negated conditional → KILLED
        if (scanline > FrameTiming.VISIBLE_SCANLINE_MAX && scanline != FrameTiming.VBLANK_END_SCANLINE){
340
            return;
341
        }
342
343
        final boolean renderingEnabled = renderingEnabled();
344 1 1. backgroundStep : negated conditional → KILLED
        if (renderingEnabled){
345 8 1. backgroundStep : changed conditional boundary → SURVIVED
2. backgroundStep : changed conditional boundary → SURVIVED
3. backgroundStep : changed conditional boundary → KILLED
4. backgroundStep : negated conditional → KILLED
5. backgroundStep : negated conditional → KILLED
6. backgroundStep : negated conditional → KILLED
7. backgroundStep : changed conditional boundary → KILLED
8. backgroundStep : negated conditional → KILLED
            final boolean inShiftRange = (dot >= 2 && dot <= HORIZONTAL_COPY_DOT)
346
                    || (dot > PREFETCH_REGION_START_DOT && dot <= PREFETCH_RELOAD_DOT);
347 1 1. backgroundStep : negated conditional → KILLED
            if (inShiftRange){
348 1 1. backgroundStep : removed call to com/rox/ppu/PPU::shiftBackgroundShiftRegisters → KILLED
                shiftBackgroundShiftRegisters();
349
            }
350
        }
351
352 6 1. backgroundStep : changed conditional boundary → KILLED
2. backgroundStep : changed conditional boundary → KILLED
3. backgroundStep : negated conditional → KILLED
4. backgroundStep : changed conditional boundary → KILLED
5. backgroundStep : negated conditional → KILLED
6. backgroundStep : negated conditional → KILLED
        if (dot >= 1 && dot <= MAIN_FETCH_REGION_END_DOT && scanline <= FrameTiming.VISIBLE_SCANLINE_MAX){
353 2 1. backgroundStep : Replaced integer subtraction with addition → KILLED
2. backgroundStep : removed call to com/rox/ppu/PPU::drawPixel → KILLED
            drawPixel(dot - 1, scanline);
354
        }
355
356 1 1. backgroundStep : negated conditional → KILLED
        if (!renderingEnabled){
357
            return;
358
        }
359
360 4 1. backgroundStep : changed conditional boundary → SURVIVED
2. backgroundStep : negated conditional → KILLED
3. backgroundStep : changed conditional boundary → KILLED
4. backgroundStep : negated conditional → KILLED
        final boolean inMainFetchRegion = dot >= 1 && dot <= MAIN_FETCH_REGION_END_DOT;
361 4 1. backgroundStep : negated conditional → KILLED
2. backgroundStep : changed conditional boundary → KILLED
3. backgroundStep : negated conditional → KILLED
4. backgroundStep : changed conditional boundary → KILLED
        final boolean inPrefetchRegion = dot >= PREFETCH_REGION_START_DOT && dot <= PREFETCH_REGION_END_DOT;
362 2 1. backgroundStep : negated conditional → KILLED
2. backgroundStep : negated conditional → KILLED
        if (inMainFetchRegion || inPrefetchRegion){
363 1 1. backgroundStep : removed call to com/rox/ppu/PPU::fetchStep → KILLED
            fetchStep();
364
        }
365 1 1. backgroundStep : negated conditional → KILLED
        if (dot == MAIN_FETCH_REGION_END_DOT){
366 1 1. backgroundStep : removed call to com/rox/ppu/PPU::incrementFineY → KILLED
            incrementFineY();
367
        }
368 1 1. backgroundStep : negated conditional → KILLED
        if (dot == HORIZONTAL_COPY_DOT){
369 1 1. backgroundStep : removed call to com/rox/ppu/PPU::reloadShiftRegisters → SURVIVED
            reloadShiftRegisters();
370 1 1. backgroundStep : removed call to com/rox/ppu/PPU::copyHorizontalBits → KILLED
            copyHorizontalBits();
371
        }
372 1 1. backgroundStep : negated conditional → KILLED
        if (dot == PREFETCH_RELOAD_DOT){
373 1 1. backgroundStep : removed call to com/rox/ppu/PPU::reloadShiftRegisters → KILLED
            reloadShiftRegisters();
374
        }
375 5 1. backgroundStep : negated conditional → SURVIVED
2. backgroundStep : changed conditional boundary → SURVIVED
3. backgroundStep : changed conditional boundary → SURVIVED
4. backgroundStep : negated conditional → SURVIVED
5. backgroundStep : negated conditional → KILLED
        if (scanline == FrameTiming.VBLANK_END_SCANLINE && dot >= VERTICAL_COPY_START_DOT && dot <= VERTICAL_COPY_END_DOT){
376 1 1. backgroundStep : removed call to com/rox/ppu/PPU::copyVerticalBits → KILLED
            copyVerticalBits();
377
        }
378
    }
379
380
    /**
381
     * The repeating 8-dot tile fetch (NT byte, attribute byte, pattern low, pattern high, coarse-X
382
     * increment) - runs during both the main fetch region (dots 1-256) and the next scanline's 2-tile
383
     * prefetch region (dots 321-336). Reload is skipped on the very first dot of either region (dot 1,
384
     * dot 321): the previous group's data was already folded in by {@link #backgroundStep()}'s explicit
385
     * dot-257/dot-337 reloads, so reloading again here would stomp the shift registers' just-shifted low
386
     * byte with stale data instead of letting it drain into the high byte - verified against nesdev's own
387
     * reload-cadence documentation (ticks 9, 17, ..., 257) before trusting this by-construction reasoning.
388
     */
389
    private void fetchStep(){
390 2 1. fetchStep : Replaced integer modulus with multiplication → KILLED
2. fetchStep : Replaced integer subtraction with addition → KILLED
        switch ((dot - 1) % TILE_FETCH_GROUP_DOTS){
391
            case 0 -> {
392 2 1. fetchStep : negated conditional → KILLED
2. fetchStep : negated conditional → KILLED
                if (dot != 1 && dot != PREFETCH_REGION_START_DOT){
393 1 1. fetchStep : removed call to com/rox/ppu/PPU::reloadShiftRegisters → KILLED
                    reloadShiftRegisters();
394
                }
395 2 1. fetchStep : Replaced bitwise AND with OR → KILLED
2. fetchStep : Replaced bitwise OR with AND → KILLED
                nextTileId = readMemory(NAMETABLE_BASE_ADDRESS | (currentVramAddress & NAMETABLE_FETCH_ADDRESS_MASK));
396
            }
397
            case 2 -> nextTilePaletteGroup = fetchAttributePaletteGroup();
398
            case 4 -> nextPatternLowByte = fetchPatternByte(0);
399
            case 6 -> nextPatternHighByte = fetchPatternByte(PATTERN_HIGH_PLANE_OFFSET);
400 1 1. fetchStep : removed call to com/rox/ppu/PPU::incrementCoarseX → KILLED
            case 7 -> incrementCoarseX();
401
            default -> { }
402
        }
403
    }
404
405
    /** The attribute byte's 2x2 grid of 2-bit palette-group values, indexed by which quadrant coarse X/Y falls in. */
406
    private int fetchAttributePaletteGroup(){
407 8 1. fetchAttributePaletteGroup : Replaced bitwise AND with OR → KILLED
2. fetchAttributePaletteGroup : Replaced bitwise OR with AND → KILLED
3. fetchAttributePaletteGroup : Replaced Shift Right with Shift Left → KILLED
4. fetchAttributePaletteGroup : Replaced bitwise AND with OR → KILLED
5. fetchAttributePaletteGroup : Replaced bitwise OR with AND → KILLED
6. fetchAttributePaletteGroup : Replaced Shift Right with Shift Left → KILLED
7. fetchAttributePaletteGroup : Replaced bitwise AND with OR → KILLED
8. fetchAttributePaletteGroup : Replaced bitwise OR with AND → KILLED
        final int attributeAddress = ATTRIBUTE_BASE_ADDRESS
408
                | (currentVramAddress & ATTRIBUTE_NAMETABLE_MASK)
409
                | ((currentVramAddress >> ATTRIBUTE_COARSE_Y_SHIFT_IN_ADDRESS) & ATTRIBUTE_COARSE_Y_ADDRESS_MASK)
410
                | ((currentVramAddress >> ATTRIBUTE_COARSE_X_SHIFT_IN_ADDRESS) & ATTRIBUTE_COARSE_X_ADDRESS_MASK);
411
        final int attributeByte = readMemory(attributeAddress);
412 1 1. fetchAttributePaletteGroup : Replaced bitwise AND with OR → KILLED
        final int coarseX = currentVramAddress & COARSE_X_MASK;
413 2 1. fetchAttributePaletteGroup : Replaced Shift Right with Shift Left → KILLED
2. fetchAttributePaletteGroup : Replaced bitwise AND with OR → KILLED
        final int coarseY = (currentVramAddress >> COARSE_Y_SHIFT) & COARSE_Y_MASK;
414 4 1. fetchAttributePaletteGroup : Replaced bitwise AND with OR → KILLED
2. fetchAttributePaletteGroup : Replaced Shift Left with Shift Right → KILLED
3. fetchAttributePaletteGroup : Replaced bitwise AND with OR → KILLED
4. fetchAttributePaletteGroup : Replaced bitwise OR with AND → KILLED
        final int quadrantShift = ((coarseY & ATTRIBUTE_QUADRANT_BIT) << 1) | (coarseX & ATTRIBUTE_QUADRANT_BIT);
415 3 1. fetchAttributePaletteGroup : replaced int return with 0 for com/rox/ppu/PPU::fetchAttributePaletteGroup → KILLED
2. fetchAttributePaletteGroup : Replaced Shift Right with Shift Left → KILLED
3. fetchAttributePaletteGroup : Replaced bitwise AND with OR → KILLED
        return (attributeByte >> quadrantShift) & ATTRIBUTE_GROUP_MASK;
416
    }
417
418
    private int fetchPatternByte(final int planeOffset){
419 2 1. fetchPatternByte : Replaced Shift Right with Shift Left → KILLED
2. fetchPatternByte : Replaced bitwise AND with OR → KILLED
        final int fineY = (currentVramAddress >> FINE_Y_SHIFT) & FINE_Y_MASK;
420 5 1. fetchPatternByte : Replaced integer addition with subtraction → KILLED
2. fetchPatternByte : replaced int return with 0 for com/rox/ppu/PPU::fetchPatternByte → KILLED
3. fetchPatternByte : Replaced integer multiplication with division → KILLED
4. fetchPatternByte : Replaced integer addition with subtraction → KILLED
5. fetchPatternByte : Replaced integer addition with subtraction → KILLED
        return readMemory(controlRegister.backgroundPatternTableBase() + nextTileId * TILE_BYTES + fineY + planeOffset);
421
    }
422
423
    /** Folds the latched tile's data into the shift registers' low byte - the high byte drains from the previous tile. */
424
    private void reloadShiftRegisters(){
425 2 1. reloadShiftRegisters : Replaced bitwise AND with OR → KILLED
2. reloadShiftRegisters : Replaced bitwise OR with AND → KILLED
        bgPatternShiftLow = (bgPatternShiftLow & SHIFT_REGISTER_LOW_BYTE_CLEAR_MASK) | nextPatternLowByte;
426 2 1. reloadShiftRegisters : Replaced bitwise OR with AND → KILLED
2. reloadShiftRegisters : Replaced bitwise AND with OR → KILLED
        bgPatternShiftHigh = (bgPatternShiftHigh & SHIFT_REGISTER_LOW_BYTE_CLEAR_MASK) | nextPatternHighByte;
427
        //the 2-bit palette group is constant for all 8 pixels of a tile, so it's broadcast across a
428
        //whole byte (all-1s or all-0s per bit) rather than genuinely tracking 8 individual bits - a
429
        //well-known, behaviourally-identical simplification of real hardware's 1-bit-latch design
430 2 1. reloadShiftRegisters : negated conditional → KILLED
2. reloadShiftRegisters : Replaced bitwise AND with OR → KILLED
        final int attributeLowFill = (nextTilePaletteGroup & 0x01) != 0 ? BYTE_MASK : 0;
431 2 1. reloadShiftRegisters : negated conditional → KILLED
2. reloadShiftRegisters : Replaced bitwise AND with OR → KILLED
        final int attributeHighFill = (nextTilePaletteGroup & 0x02) != 0 ? BYTE_MASK : 0;
432 2 1. reloadShiftRegisters : Replaced bitwise AND with OR → KILLED
2. reloadShiftRegisters : Replaced bitwise OR with AND → KILLED
        bgAttributeShiftLow = (bgAttributeShiftLow & SHIFT_REGISTER_LOW_BYTE_CLEAR_MASK) | attributeLowFill;
433 2 1. reloadShiftRegisters : Replaced bitwise OR with AND → KILLED
2. reloadShiftRegisters : Replaced bitwise AND with OR → KILLED
        bgAttributeShiftHigh = (bgAttributeShiftHigh & SHIFT_REGISTER_LOW_BYTE_CLEAR_MASK) | attributeHighFill;
434
    }
435
436
    private void shiftBackgroundShiftRegisters(){
437 2 1. shiftBackgroundShiftRegisters : Replaced bitwise AND with OR → KILLED
2. shiftBackgroundShiftRegisters : Replaced Shift Left with Shift Right → KILLED
        bgPatternShiftLow = (bgPatternShiftLow << 1) & SHIFT_REGISTER_MASK;
438 2 1. shiftBackgroundShiftRegisters : Replaced bitwise AND with OR → KILLED
2. shiftBackgroundShiftRegisters : Replaced Shift Left with Shift Right → KILLED
        bgPatternShiftHigh = (bgPatternShiftHigh << 1) & SHIFT_REGISTER_MASK;
439 2 1. shiftBackgroundShiftRegisters : Replaced bitwise AND with OR → KILLED
2. shiftBackgroundShiftRegisters : Replaced Shift Left with Shift Right → KILLED
        bgAttributeShiftLow = (bgAttributeShiftLow << 1) & SHIFT_REGISTER_MASK;
440 2 1. shiftBackgroundShiftRegisters : Replaced Shift Left with Shift Right → KILLED
2. shiftBackgroundShiftRegisters : Replaced bitwise AND with OR → KILLED
        bgAttributeShiftHigh = (bgAttributeShiftHigh << 1) & SHIFT_REGISTER_MASK;
441
    }
442
443
    /** nesdev's standard coarse-X increment: wraps at 31, toggling the horizontal nametable-select bit. */
444
    private void incrementCoarseX(){
445 2 1. incrementCoarseX : negated conditional → KILLED
2. incrementCoarseX : Replaced bitwise AND with OR → KILLED
        if ((currentVramAddress & COARSE_X_MASK) == COARSE_X_MAX){
446 2 1. incrementCoarseX : Replaced XOR with AND → KILLED
2. incrementCoarseX : Replaced bitwise AND with OR → KILLED
            currentVramAddress = (currentVramAddress & ~COARSE_X_MASK) ^ NAMETABLE_X_TOGGLE_BIT;
447
        } else {
448 2 1. incrementCoarseX : Replaced integer addition with subtraction → KILLED
2. incrementCoarseX : Replaced bitwise AND with OR → KILLED
            currentVramAddress = (currentVramAddress + 1) & LOOPY_REGISTER_MASK;
449
        }
450
    }
451
452
    /**
453
     * nesdev's standard fine/coarse-Y increment (dot 256 only): fine Y wraps into coarse Y, which
454
     * itself wraps at 29 (the real last row of tiles, toggling the vertical nametable-select bit) - but
455
     * at 31 (a coarse Y a game deliberately set out of bounds, into the attribute table) wraps to 0
456
     * *without* toggling the nametable bit, since that out-of-bounds value was never really "on" the
457
     * next nametable to begin with.
458
     */
459
    private void incrementFineY(){
460 2 1. incrementFineY : negated conditional → KILLED
2. incrementFineY : Replaced bitwise AND with OR → KILLED
        if ((currentVramAddress & FINE_Y_FULL_MASK) != FINE_Y_FULL_MASK){
461 2 1. incrementFineY : Replaced integer addition with subtraction → KILLED
2. incrementFineY : Replaced bitwise AND with OR → KILLED
            currentVramAddress = (currentVramAddress + (1 << FINE_Y_SHIFT)) & LOOPY_REGISTER_MASK;
462
            return;
463
        }
464 1 1. incrementFineY : Replaced bitwise AND with OR → KILLED
        currentVramAddress &= ~FINE_Y_FULL_MASK;
465 2 1. incrementFineY : Replaced Shift Right with Shift Left → KILLED
2. incrementFineY : Replaced bitwise AND with OR → KILLED
        int coarseY = (currentVramAddress >> COARSE_Y_SHIFT) & COARSE_Y_MASK;
466 1 1. incrementFineY : negated conditional → KILLED
        if (coarseY == COARSE_Y_WRAP_WITH_TOGGLE){
467
            coarseY = 0;
468 1 1. incrementFineY : Replaced XOR with AND → KILLED
            currentVramAddress ^= NAMETABLE_Y_TOGGLE_BIT;
469 1 1. incrementFineY : negated conditional → KILLED
        } else if (coarseY == COARSE_Y_WRAP_WITHOUT_TOGGLE){
470
            coarseY = 0;
471
        } else {
472 1 1. incrementFineY : Changed increment from 1 to -1 → KILLED
            coarseY++;
473
        }
474 4 1. incrementFineY : Replaced bitwise AND with OR → KILLED
2. incrementFineY : Replaced Shift Left with Shift Right → KILLED
3. incrementFineY : Replaced bitwise OR with AND → KILLED
4. incrementFineY : Replaced bitwise AND with OR → KILLED
        currentVramAddress = ((currentVramAddress & COARSE_Y_CLEAR_MASK) | (coarseY << COARSE_Y_SHIFT)) & LOOPY_REGISTER_MASK;
475
    }
476
477
    /** hori(v)=hori(t): copies coarse X + the horizontal nametable-select bit, dot 257 only. */
478
    private void copyHorizontalBits(){
479 4 1. copyHorizontalBits : Replaced bitwise OR with AND → KILLED
2. copyHorizontalBits : Replaced bitwise AND with OR → KILLED
3. copyHorizontalBits : Replaced bitwise AND with OR → KILLED
4. copyHorizontalBits : Replaced bitwise AND with OR → KILLED
        currentVramAddress = ((currentVramAddress & ~HORIZONTAL_COPY_MASK)
480
                | (temporaryVramAddress & HORIZONTAL_COPY_MASK)) & LOOPY_REGISTER_MASK;
481
    }
482
483
    /** vert(v)=vert(t): copies fine Y + coarse Y + the vertical nametable-select bit, pre-render dots 280-304. */
484
    private void copyVerticalBits(){
485 4 1. copyVerticalBits : Replaced bitwise AND with OR → KILLED
2. copyVerticalBits : Replaced bitwise OR with AND → KILLED
3. copyVerticalBits : Replaced bitwise AND with OR → KILLED
4. copyVerticalBits : Replaced bitwise AND with OR → KILLED
        currentVramAddress = ((currentVramAddress & ~VERTICAL_COPY_MASK)
486
                | (temporaryVramAddress & VERTICAL_COPY_MASK)) & LOOPY_REGISTER_MASK;
487
    }
488
489
    private boolean renderingEnabled(){
490 2 1. renderingEnabled : replaced boolean return with false for com/rox/ppu/PPU::renderingEnabled → KILLED
2. renderingEnabled : replaced boolean return with true for com/rox/ppu/PPU::renderingEnabled → KILLED
        return maskRegister.renderingEnabled();
491
    }
492
493
    /**
494
     * Runs on every dot of every visible (0-239) and pre-render (261) scanline, mirroring
495
     * {@link #backgroundStep()}'s scanline range. Builds secondary OAM for the scanline about to start
496
     * at dot 65 (real hardware: dots 65-256) and fetches that scanline's sprite pattern bytes at dot 257
497
     * (real hardware: dots 257-320) - see the class javadoc's sprite-pipeline simplification note for why
498
     * collapsing each multi-dot window into a single dot is behaviourally identical.
499
     */
500
    private void spriteStep(){
501 3 1. spriteStep : changed conditional boundary → SURVIVED
2. spriteStep : negated conditional → KILLED
3. spriteStep : negated conditional → KILLED
        if (scanline > FrameTiming.VISIBLE_SCANLINE_MAX && scanline != FrameTiming.VBLANK_END_SCANLINE){
502
            return;
503
        }
504 1 1. spriteStep : negated conditional → KILLED
        if (!renderingEnabled()){
505
            return;
506
        }
507 1 1. spriteStep : negated conditional → SURVIVED
        if (dot == SPRITE_EVALUATION_DOT){
508 1 1. spriteStep : removed call to com/rox/ppu/PPU::evaluateSpritesForNextScanline → KILLED
            evaluateSpritesForNextScanline();
509
        }
510 1 1. spriteStep : negated conditional → KILLED
        if (dot == HORIZONTAL_COPY_DOT){ //dot 257, same dot as background's hori(v)=hori(t) copy
511 1 1. spriteStep : removed call to com/rox/ppu/PPU::fetchSpritesForNextScanline → KILLED
            fetchSpritesForNextScanline();
512
        }
513
    }
514
515
    /**
516
     * Builds secondary OAM (up to 8 sprites) for the scanline about to start, scanning primary OAM in
517
     * index order so slot 0 of secondary OAM (if occupied) is always the highest-priority sprite in
518
     * range - OAM index 0 specifically is also tracked (via {@link #secondaryOamSpriteZeroSlot}) for
519
     * sprite-0-hit detection. Sets {@link #spriteOverflow} (sticky until the pre-render scanline clears
520
     * it) when more than 8 sprites are in range; see the class javadoc for why this doesn't reproduce
521
     * real hardware's buggy overflow detection.
522
     *
523
     * <p>OAM byte 0 stores the sprite's top scanline <em>minus one</em> (real hardware's documented
524
     * "Y position" quirk - see nesdev's {@code PPU_OAM} page) - a sprite with {@code Y=N} is visible on
525
     * scanlines {@code N+1..N+height}, never on scanline 0 no matter what {@code Y} is. That {@code -1}
526
     * is folded into {@code row} below, and falls out naturally for the pre-render scanline's target of
527
     * 0: {@code row} is then always negative, so no sprite is ever found in range - correctly matching
528
     * real hardware's own "sprites are never displayed on the first line" behaviour without needing a
529
     * separate check.
530
     */
531
    private void evaluateSpritesForNextScanline(){
532 2 1. evaluateSpritesForNextScanline : Replaced integer addition with subtraction → KILLED
2. evaluateSpritesForNextScanline : negated conditional → KILLED
        final int targetScanline = scanline == FrameTiming.VBLANK_END_SCANLINE ? 0 : scanline + 1;
533 1 1. evaluateSpritesForNextScanline : negated conditional → KILLED
        final int spriteHeight = controlRegister.tallSprites() ? SPRITE_HEIGHT_TALL : SPRITE_HEIGHT_SHORT;
534
        int found = 0;
535
        int spriteZeroSlot = -1;
536
        boolean overflow = false;
537 2 1. evaluateSpritesForNextScanline : changed conditional boundary → KILLED
2. evaluateSpritesForNextScanline : negated conditional → KILLED
        for (int i = 0; i < OAM_SPRITE_COUNT; i++){
538 1 1. evaluateSpritesForNextScanline : Replaced integer multiplication with division → KILLED
            final int base = i * OAM_BYTES_PER_SPRITE;
539 2 1. evaluateSpritesForNextScanline : Replaced integer subtraction with addition → KILLED
2. evaluateSpritesForNextScanline : Replaced integer subtraction with addition → KILLED
            final int row = targetScanline - oam[base] - 1;
540 4 1. evaluateSpritesForNextScanline : changed conditional boundary → SURVIVED
2. evaluateSpritesForNextScanline : negated conditional → KILLED
3. evaluateSpritesForNextScanline : changed conditional boundary → KILLED
4. evaluateSpritesForNextScanline : negated conditional → KILLED
            if (row < 0 || row >= spriteHeight){
541
                continue;
542
            }
543 2 1. evaluateSpritesForNextScanline : changed conditional boundary → KILLED
2. evaluateSpritesForNextScanline : negated conditional → KILLED
            if (found < MAX_SPRITES_PER_SCANLINE){
544 1 1. evaluateSpritesForNextScanline : Replaced integer multiplication with division → KILLED
                final int destBase = found * OAM_BYTES_PER_SPRITE;
545
                secondaryOam[destBase] = oam[base];
546 2 1. evaluateSpritesForNextScanline : Replaced integer addition with subtraction → KILLED
2. evaluateSpritesForNextScanline : Replaced integer addition with subtraction → KILLED
                secondaryOam[destBase + 1] = oam[base + 1];
547 2 1. evaluateSpritesForNextScanline : Replaced integer addition with subtraction → KILLED
2. evaluateSpritesForNextScanline : Replaced integer addition with subtraction → KILLED
                secondaryOam[destBase + 2] = oam[base + 2];
548 2 1. evaluateSpritesForNextScanline : Replaced integer addition with subtraction → KILLED
2. evaluateSpritesForNextScanline : Replaced integer addition with subtraction → KILLED
                secondaryOam[destBase + 3] = oam[base + 3];
549 1 1. evaluateSpritesForNextScanline : negated conditional → KILLED
                if (i == 0){
550
                    spriteZeroSlot = found;
551
                }
552 1 1. evaluateSpritesForNextScanline : Changed increment from 1 to -1 → KILLED
                found++;
553
            } else {
554
                overflow = true;
555
            }
556
        }
557
        secondaryOamCount = found;
558
        secondaryOamSpriteZeroSlot = spriteZeroSlot;
559 1 1. evaluateSpritesForNextScanline : negated conditional → KILLED
        if (overflow){
560
            spriteOverflow = true;
561
        }
562
    }
563
564
    /**
565
     * Fetches pattern-table bytes for every sprite {@link #evaluateSpritesForNextScanline()} just found,
566
     * for the scanline about to start. Handles 8x8 vs 8x16 sizing ({@code $2000} bit 5; for 8x16, the
567
     * tile index's own low bit selects the pattern table and its high bits pick which of the pair of
568
     * tiles) and vertical/horizontal flip - horizontal flip is resolved here, once, by reversing the
569
     * fetched byte's bit order, rather than being checked per pixel at draw time.
570
     */
571
    private void fetchSpritesForNextScanline(){
572 2 1. fetchSpritesForNextScanline : Replaced integer addition with subtraction → KILLED
2. fetchSpritesForNextScanline : negated conditional → KILLED
        final int targetScanline = scanline == FrameTiming.VBLANK_END_SCANLINE ? 0 : scanline + 1;
573
        final boolean tallSpritesEnabled = controlRegister.tallSprites();
574 1 1. fetchSpritesForNextScanline : negated conditional → KILLED
        final int spriteHeight = tallSpritesEnabled ? SPRITE_HEIGHT_TALL : SPRITE_HEIGHT_SHORT;
575 2 1. fetchSpritesForNextScanline : negated conditional → KILLED
2. fetchSpritesForNextScanline : changed conditional boundary → KILLED
        for (int slot = 0; slot < secondaryOamCount; slot++){
576 1 1. fetchSpritesForNextScanline : Replaced integer multiplication with division → KILLED
            final int base = slot * OAM_BYTES_PER_SPRITE;
577
            final int spriteY = secondaryOam[base];
578 1 1. fetchSpritesForNextScanline : Replaced integer addition with subtraction → KILLED
            final int tileIndex = secondaryOam[base + 1];
579 1 1. fetchSpritesForNextScanline : Replaced integer addition with subtraction → KILLED
            final int attributes = secondaryOam[base + 2];
580 2 1. fetchSpritesForNextScanline : Replaced bitwise AND with OR → KILLED
2. fetchSpritesForNextScanline : negated conditional → KILLED
            final boolean flipV = (attributes & SPRITE_FLIP_VERTICAL_BIT) != 0;
581 2 1. fetchSpritesForNextScanline : negated conditional → KILLED
2. fetchSpritesForNextScanline : Replaced bitwise AND with OR → KILLED
            final boolean flipH = (attributes & SPRITE_FLIP_HORIZONTAL_BIT) != 0;
582
583 2 1. fetchSpritesForNextScanline : Replaced integer subtraction with addition → KILLED
2. fetchSpritesForNextScanline : Replaced integer subtraction with addition → KILLED
            int row = targetScanline - spriteY - 1; //OAM Y quirk - see evaluateSpritesForNextScanline()
584 1 1. fetchSpritesForNextScanline : negated conditional → KILLED
            if (flipV){
585 2 1. fetchSpritesForNextScanline : Replaced integer subtraction with addition → KILLED
2. fetchSpritesForNextScanline : Replaced integer subtraction with addition → KILLED
                row = spriteHeight - 1 - row;
586
            }
587
            final int patternTableBase;
588
            final int patternTileIndex;
589 1 1. fetchSpritesForNextScanline : negated conditional → KILLED
            if (tallSpritesEnabled){
590 1 1. fetchSpritesForNextScanline : negated conditional → KILLED
                patternTableBase = isBitSet(0, tileIndex) ? TALL_SPRITE_PATTERN_TABLE_SIZE : 0;
591 1 1. fetchSpritesForNextScanline : Replaced bitwise AND with OR → KILLED
                final int topTile = tileIndex & 0xFE;
592 2 1. fetchSpritesForNextScanline : changed conditional boundary → KILLED
2. fetchSpritesForNextScanline : negated conditional → KILLED
                if (row >= SPRITE_HEIGHT_SHORT){
593
                    patternTileIndex = withBitSet(topTile, 0);
594 1 1. fetchSpritesForNextScanline : Changed increment from -8 to 8 → KILLED
                    row -= SPRITE_HEIGHT_SHORT;
595
                } else {
596
                    patternTileIndex = topTile;
597
                }
598
            } else {
599
                patternTableBase = controlRegister.spritePatternTableBase();
600
                patternTileIndex = tileIndex;
601
            }
602
603 3 1. fetchSpritesForNextScanline : Replaced integer addition with subtraction → KILLED
2. fetchSpritesForNextScanline : Replaced integer addition with subtraction → KILLED
3. fetchSpritesForNextScanline : Replaced integer multiplication with division → KILLED
            int lowByte = readMemory(patternTableBase + patternTileIndex * TILE_BYTES + row);
604 4 1. fetchSpritesForNextScanline : Replaced integer addition with subtraction → KILLED
2. fetchSpritesForNextScanline : Replaced integer multiplication with division → KILLED
3. fetchSpritesForNextScanline : Replaced integer addition with subtraction → KILLED
4. fetchSpritesForNextScanline : Replaced integer addition with subtraction → KILLED
            int highByte = readMemory(patternTableBase + patternTileIndex * TILE_BYTES + row + PATTERN_HIGH_PLANE_OFFSET);
605 1 1. fetchSpritesForNextScanline : negated conditional → KILLED
            if (flipH){
606
                lowByte = reverseBits(lowByte);
607
                highByte = reverseBits(highByte);
608
            }
609
610
            spritePatternLowByte[slot] = lowByte;
611
            spritePatternHighByte[slot] = highByte;
612
            spriteAttributes[slot] = attributes;
613 1 1. fetchSpritesForNextScanline : Replaced integer addition with subtraction → KILLED
            spriteXPosition[slot] = secondaryOam[base + 3];
614 1 1. fetchSpritesForNextScanline : negated conditional → KILLED
            spriteIsZero[slot] = slot == secondaryOamSpriteZeroSlot;
615
        }
616
        //real hardware always fetches all 8 sprite slots every scanline - unused slots (secondary OAM
617
        //left at its $FF clear value) still perform a "dummy" tile-$FF fetch, discarded here since
618
        //activeSpriteCount below excludes them from rendering. Skipping these dummy reads entirely (as
619
        //this loop used to) is invisible to on-screen NROM/MMC1 output, but MMC3 games rely on exactly
620
        //these reads for their once-per-scanline A12 toggle (via Mmc3Mapper.readChr()) whenever a
621
        //scanline has fewer than 8 real sprites - the common case - so omitting them starves the MMC3
622
        //IRQ counter of the edges it needs.
623 2 1. fetchSpritesForNextScanline : changed conditional boundary → SURVIVED
2. fetchSpritesForNextScanline : negated conditional → TIMED_OUT
        for (int slot = secondaryOamCount; slot < MAX_SPRITES_PER_SCANLINE; slot++){
624 1 1. fetchSpritesForNextScanline : negated conditional → SURVIVED
            final int dummyPatternTableBase = tallSpritesEnabled ? TALL_SPRITE_PATTERN_TABLE_SIZE : controlRegister.spritePatternTableBase();
625 1 1. fetchSpritesForNextScanline : negated conditional → SURVIVED
            final int dummyTileIndex = tallSpritesEnabled ? DUMMY_SPRITE_TILE_INDEX & 0xFE : DUMMY_SPRITE_TILE_INDEX;
626 2 1. fetchSpritesForNextScanline : Replaced integer addition with subtraction → SURVIVED
2. fetchSpritesForNextScanline : Replaced integer multiplication with division → SURVIVED
            readMemory(dummyPatternTableBase + dummyTileIndex * TILE_BYTES);
627 3 1. fetchSpritesForNextScanline : Replaced integer addition with subtraction → SURVIVED
2. fetchSpritesForNextScanline : Replaced integer multiplication with division → SURVIVED
3. fetchSpritesForNextScanline : Replaced integer addition with subtraction → SURVIVED
            readMemory(dummyPatternTableBase + dummyTileIndex * TILE_BYTES + PATTERN_HIGH_PLANE_OFFSET);
628
        }
629
        activeSpriteCount = secondaryOamCount;
630
    }
631
632
    /** Reverses an 8-bit value's bit order - implements horizontal sprite flip on a fetched pattern byte. */
633
    private static int reverseBits(final int value){
634
        int result = 0;
635
        int remaining = value;
636 2 1. reverseBits : negated conditional → KILLED
2. reverseBits : changed conditional boundary → KILLED
        for (int bit = 0; bit < 8; bit++){
637 3 1. reverseBits : Replaced Shift Left with Shift Right → KILLED
2. reverseBits : Replaced bitwise AND with OR → KILLED
3. reverseBits : Replaced bitwise OR with AND → KILLED
            result = (result << 1) | (remaining & 0x01);
638 1 1. reverseBits : Replaced Shift Right with Shift Left → KILLED
            remaining >>= 1;
639
        }
640 1 1. reverseBits : replaced int return with 0 for com/rox/ppu/PPU::reverseBits → KILLED
        return result;
641
    }
642
643
    /**
644
     * Resolves one framebuffer pixel by compositing the background shift-register state (selected by
645
     * {@link #fineXScroll}, as in Phase 3/4) with up to 8 active sprites for this scanline, in OAM-index
646
     * priority order - the first opaque sprite found wins, both for the final colour (subject to that
647
     * sprite's own front/back priority bit against an opaque background pixel) and for sprite-0-hit
648
     * detection, since OAM index 0 (if in range) is always secondary-OAM slot 0. Falls back to the
649
     * backdrop colour ({@code $3F00}) when nothing is opaque - real hardware's "universal background
650
     * colour" quirk, same as background-only rendering already relied on.
651
     */
652
    private void drawPixel(final int x, final int y){
653 4 1. drawPixel : negated conditional → KILLED
2. drawPixel : negated conditional → KILLED
3. drawPixel : negated conditional → KILLED
4. drawPixel : changed conditional boundary → KILLED
        final boolean backgroundVisible = maskRegister.showBackground() && (x >= 8 || maskRegister.showBackgroundLeft());
654
655
        int paletteRamIndex = 0; //the universal backdrop colour, $3F00
656
        int bgPixelValue = 0;
657 1 1. drawPixel : negated conditional → KILLED
        if (backgroundVisible){
658 1 1. drawPixel : Replaced Shift Right with Shift Left → KILLED
            final int bitMux = PIXEL_MUX_MSB >> fineXScroll;
659 2 1. drawPixel : negated conditional → KILLED
2. drawPixel : Replaced bitwise AND with OR → KILLED
            bgPixelValue = (((bgPatternShiftHigh & bitMux) != 0) ? 2 : 0)
660 3 1. drawPixel : Replaced bitwise AND with OR → KILLED
2. drawPixel : negated conditional → KILLED
3. drawPixel : Replaced bitwise OR with AND → KILLED
                    | (((bgPatternShiftLow & bitMux) != 0) ? 1 : 0);
661 1 1. drawPixel : negated conditional → KILLED
            if (bgPixelValue != 0){
662 2 1. drawPixel : negated conditional → KILLED
2. drawPixel : Replaced bitwise AND with OR → KILLED
                final int paletteGroup = (((bgAttributeShiftHigh & bitMux) != 0) ? 2 : 0)
663 3 1. drawPixel : Replaced bitwise AND with OR → KILLED
2. drawPixel : negated conditional → KILLED
3. drawPixel : Replaced bitwise OR with AND → KILLED
                        | (((bgAttributeShiftLow & bitMux) != 0) ? 1 : 0);
664 3 1. drawPixel : Replaced Shift Left with Shift Right → KILLED
2. drawPixel : Replaced integer addition with subtraction → KILLED
3. drawPixel : Replaced integer addition with subtraction → KILLED
                paletteRamIndex = resolvePaletteIndex(PALETTE_START_ADDRESS + (paletteGroup << 2) + bgPixelValue);
665
            }
666
        }
667
668 4 1. drawPixel : changed conditional boundary → SURVIVED
2. drawPixel : negated conditional → KILLED
3. drawPixel : negated conditional → KILLED
4. drawPixel : negated conditional → KILLED
        final boolean spritesVisible = maskRegister.showSprites() && (x >= 8 || maskRegister.showSpritesLeft());
669 1 1. drawPixel : negated conditional → KILLED
        if (spritesVisible){
670 2 1. drawPixel : negated conditional → KILLED
2. drawPixel : changed conditional boundary → KILLED
            for (int slot = 0; slot < activeSpriteCount; slot++){
671 1 1. drawPixel : Replaced integer subtraction with addition → KILLED
                final int offset = x - spriteXPosition[slot];
672 4 1. drawPixel : changed conditional boundary → KILLED
2. drawPixel : changed conditional boundary → KILLED
3. drawPixel : negated conditional → KILLED
4. drawPixel : negated conditional → KILLED
                if (offset < 0 || offset > 7){
673
                    continue;
674
                }
675 1 1. drawPixel : Replaced Shift Right with Shift Left → KILLED
                final int spriteBitMux = 0x80 >> offset;
676 2 1. drawPixel : Replaced bitwise AND with OR → KILLED
2. drawPixel : negated conditional → KILLED
                final int spritePixelValue = (((spritePatternHighByte[slot] & spriteBitMux) != 0) ? 2 : 0)
677 3 1. drawPixel : Replaced bitwise OR with AND → KILLED
2. drawPixel : negated conditional → KILLED
3. drawPixel : Replaced bitwise AND with OR → KILLED
                        | (((spritePatternLowByte[slot] & spriteBitMux) != 0) ? 1 : 0);
678 1 1. drawPixel : negated conditional → KILLED
                if (spritePixelValue == 0){
679
                    continue;
680
                }
681 3 1. drawPixel : negated conditional → KILLED
2. drawPixel : negated conditional → KILLED
3. drawPixel : negated conditional → KILLED
                if (spriteIsZero[slot] && bgPixelValue != 0 && x != SPRITE_ZERO_HIT_EXCLUDED_X){
682
                    spriteZeroHitFlag = true;
683
                }
684 2 1. drawPixel : negated conditional → KILLED
2. drawPixel : Replaced bitwise AND with OR → KILLED
                final boolean behindBackground = (spriteAttributes[slot] & SPRITE_PRIORITY_BEHIND_BACKGROUND_BIT) != 0;
685 2 1. drawPixel : negated conditional → KILLED
2. drawPixel : negated conditional → KILLED
                if (bgPixelValue == 0 || !behindBackground){
686 1 1. drawPixel : Replaced bitwise AND with OR → KILLED
                    final int paletteGroup = spriteAttributes[slot] & SPRITE_PALETTE_MASK;
687 3 1. drawPixel : Replaced Shift Left with Shift Right → KILLED
2. drawPixel : Replaced integer addition with subtraction → KILLED
3. drawPixel : Replaced integer addition with subtraction → KILLED
                    paletteRamIndex = resolvePaletteIndex(PALETTE_START_ADDRESS + SPRITE_PALETTE_RAM_OFFSET
688
                            + (paletteGroup << 2) + spritePixelValue);
689
                }
690
                break; //OAM-index priority: the first opaque sprite found wins, both for colour and hit detection
691
            }
692
        }
693 3 1. drawPixel : Replaced bitwise AND with OR → KILLED
2. drawPixel : Replaced integer multiplication with division → KILLED
3. drawPixel : Replaced integer addition with subtraction → KILLED
        framebuffer[y * FRAMEBUFFER_WIDTH + x] = paletteRam[paletteRamIndex] & PALETTE_COLOR_MASK;
694
    }
695
696
    private void setVblankFlag(final boolean asserted){
697
        vblankFlag = asserted;
698 1 1. setVblankFlag : removed call to com/rox/ppu/PPU::updateNmiLine → KILLED
        updateNmiLine();
699
    }
700
701
    /** NMI is a level (vblank && enabled) with edge detection, not a one-shot check at vblank start. */
702
    private void updateNmiLine(){
703 2 1. updateNmiLine : negated conditional → KILLED
2. updateNmiLine : negated conditional → KILLED
        final boolean currentNmiLine = vblankFlag && controlRegister.nmiEnabled();
704 2 1. updateNmiLine : negated conditional → KILLED
2. updateNmiLine : negated conditional → KILLED
        if (currentNmiLine && !previousNmiLine){
705
            nmiEdgePending = true;
706
        }
707
        previousNmiLine = currentNmiLine;
708
    }
709
710
    /** True exactly once per vblank/NMI-enable rising edge - the caller drives cpu.signalNMI() from this. */
711
    public boolean consumeNmiEdge(){
712 1 1. consumeNmiEdge : negated conditional → KILLED
        if (nmiEdgePending){
713
            nmiEdgePending = false;
714 1 1. consumeNmiEdge : replaced boolean return with false for com/rox/ppu/PPU::consumeNmiEdge → KILLED
            return true;
715
        }
716 1 1. consumeNmiEdge : replaced boolean return with true for com/rox/ppu/PPU::consumeNmiEdge → KILLED
        return false;
717
    }
718
719
    @Override
720
    public int read(final int address){
721 1 1. read : Replaced bitwise AND with OR → KILLED
        return switch (address & RegisterAddress.MASK){
722
            case RegisterAddress.PPUSTATUS -> readStatusRegister();
723
            case RegisterAddress.OAMDATA -> oam[oamAddress];
724
            case RegisterAddress.PPUDATA -> readDataRegister();
725
            default -> 0; //write-only registers: real hardware returns open bus, unmodeled here
726
        };
727
    }
728
729
    @Override
730
    public void write(final int address, final int value){
731 1 1. write : Replaced bitwise AND with OR → KILLED
        switch (address & RegisterAddress.MASK){
732 1 1. write : removed call to com/rox/ppu/PPU::writeControlRegister → KILLED
            case RegisterAddress.PPUCTRL -> writeControlRegister(value);
733
            case RegisterAddress.PPUMASK -> maskRegister = new PPUMaskRegister(value);
734 1 1. write : Replaced bitwise AND with OR → KILLED
            case RegisterAddress.OAMADDR -> oamAddress = value & BYTE_MASK;
735 1 1. write : removed call to com/rox/ppu/PPU::writeOamData → KILLED
            case RegisterAddress.OAMDATA -> writeOamData(value);
736 1 1. write : removed call to com/rox/ppu/PPU::writeScrollRegister → KILLED
            case RegisterAddress.PPUSCROLL -> writeScrollRegister(value);
737 1 1. write : removed call to com/rox/ppu/PPU::writeAddressRegister → KILLED
            case RegisterAddress.PPUADDR -> writeAddressRegister(value);
738 1 1. write : removed call to com/rox/ppu/PPU::writeDataRegister → KILLED
            case RegisterAddress.PPUDATA -> writeDataRegister(value);
739
            default -> { }
740
        }
741
    }
742
743
    /**
744
     * Handle a $2000 write - see {@link PPUControlRegister} for the full bit layout. Bit-level decoding
745
     * lives there; this method's own remaining concern is the nametable-select bits' side effect on the
746
     * loopy {@code t} register (latched into its nametable-select bits, 10-11) - takes effect the next
747
     * time {@code v} is reloaded from {@code t} (a $2006 second write, or the rendering pipeline's own
748
     * horizontal/vertical copies) - and re-checking the NMI line, since bit 7 can change it.
749
     */
750
    private void writeControlRegister(final int value){
751
        controlRegister = new PPUControlRegister(value);
752 1 1. writeControlRegister : Replaced bitwise AND with OR → KILLED
        temporaryVramAddress = (temporaryVramAddress & NAMETABLE_SELECT_CLEAR_MASK)
753 2 1. writeControlRegister : Replaced bitwise OR with AND → KILLED
2. writeControlRegister : Replaced Shift Left with Shift Right → KILLED
                | (controlRegister.nametableSelect() << NAMETABLE_SELECT_SHIFT);
754 1 1. writeControlRegister : removed call to com/rox/ppu/PPU::updateNmiLine → KILLED
        updateNmiLine();
755
    }
756
757
    /**
758
     * Handle a $2002 read: vblank flag in bit 7, sprite-0-hit in bit 6, sprite overflow in bit 5.
759
     * Clears the vblank flag and resets the write-latch shared by $2005/$2006 - sprite-0-hit and
760
     * overflow are *not* cleared by this read, only by the pre-render scanline's dot 1 (see
761
     * {@link #advanceDot()}), matching real hardware.
762
     *
763
     * Deliberately does *not* call {@link #updateNmiLine()}: doing so here can only ever matter on a
764
     * falling transition (this read only ever clears vblankFlag, never sets it), which never sets
765
     * {@code nmiEdgePending} - and the pre-render scanline's own {@link #setVblankFlag(boolean)} call
766
     * always runs again before any later rising edge is possible, correctly resyncing
767
     * {@code previousNmiLine} by then regardless. Confirmed by simulation, not just by inspection.
768
     */
769
    private int readStatusRegister(){
770 1 1. readStatusRegister : negated conditional → KILLED
        int result = vblankFlag ? VBLANK_STATUS_BIT : 0;
771 2 1. readStatusRegister : negated conditional → KILLED
2. readStatusRegister : Replaced bitwise OR with AND → KILLED
        result |= spriteZeroHitFlag ? SPRITE_ZERO_HIT_STATUS_BIT : 0;
772 2 1. readStatusRegister : negated conditional → KILLED
2. readStatusRegister : Replaced bitwise OR with AND → KILLED
        result |= spriteOverflow ? SPRITE_OVERFLOW_STATUS_BIT : 0;
773
        vblankFlag = false;
774
        writeToggle = false;
775 1 1. readStatusRegister : replaced int return with 0 for com/rox/ppu/PPU::readStatusRegister → KILLED
        return result;
776
    }
777
778
    private void writeOamData(final int value){
779 1 1. writeOamData : Replaced bitwise AND with OR → KILLED
        oam[oamAddress] = value & BYTE_MASK;
780 2 1. writeOamData : Replaced integer addition with subtraction → KILLED
2. writeOamData : Replaced bitwise AND with OR → KILLED
        oamAddress = (oamAddress + 1) & OAM_ADDRESS_MASK;
781
    }
782
783
    /**
784
     * Handle a $2005 write (loopy model): first write sets {@link #fineXScroll} and
785
     * {@link #temporaryVramAddress}'s coarse X bits (0-4); second write sets its fine Y bits (12-14)
786
     * and coarse Y bits (5-9). The legacy {@link #scrollX()}/{@link #scrollY()} test accessors
787
     * reconstruct the original byte values from these fields.
788
     */
789
    private void writeScrollRegister(final int value){
790 1 1. writeScrollRegister : negated conditional → KILLED
        if (!writeToggle){
791 1 1. writeScrollRegister : Replaced bitwise AND with OR → KILLED
            fineXScroll = value & FINE_X_MASK;
792 3 1. writeScrollRegister : Replaced Shift Right with Shift Left → KILLED
2. writeScrollRegister : Replaced bitwise AND with OR → KILLED
3. writeScrollRegister : Replaced bitwise OR with AND → KILLED
            temporaryVramAddress = (temporaryVramAddress & COARSE_X_CLEAR_MASK) | (value >> 3);
793
        } else {
794 4 1. writeScrollRegister : Replaced bitwise AND with OR → KILLED
2. writeScrollRegister : Replaced bitwise OR with AND → KILLED
3. writeScrollRegister : Replaced Shift Left with Shift Right → KILLED
4. writeScrollRegister : Replaced bitwise AND with OR → KILLED
            temporaryVramAddress = (temporaryVramAddress & FINE_Y_CLEAR_MASK) | ((value & FINE_X_MASK) << FINE_Y_SHIFT);
795 4 1. writeScrollRegister : Replaced bitwise AND with OR → KILLED
2. writeScrollRegister : Replaced Shift Right with Shift Left → KILLED
3. writeScrollRegister : Replaced bitwise OR with AND → KILLED
4. writeScrollRegister : Replaced Shift Left with Shift Right → KILLED
            temporaryVramAddress = (temporaryVramAddress & COARSE_Y_CLEAR_MASK) | ((value >> 3) << COARSE_Y_SHIFT);
796
        }
797 1 1. writeScrollRegister : negated conditional → KILLED
        writeToggle = !writeToggle;
798
    }
799
800
    /**
801
     * Handle a $2006 write (loopy model): first write sets {@link #temporaryVramAddress}'s high 6 bits
802
     * (8-13) and clears the unused 15th bit; second write sets its low 8 bits and latches
803
     * {@code currentVramAddress = temporaryVramAddress} - real hardware only updates the *visible*
804
     * VRAM address on the second write, not the first.
805
     */
806
    private void writeAddressRegister(final int value){
807 1 1. writeAddressRegister : negated conditional → KILLED
        if (!writeToggle){
808 5 1. writeAddressRegister : Replaced Shift Left with Shift Right → KILLED
2. writeAddressRegister : Replaced bitwise OR with AND → KILLED
3. writeAddressRegister : Replaced bitwise AND with OR → KILLED
4. writeAddressRegister : Replaced bitwise AND with OR → KILLED
5. writeAddressRegister : Replaced bitwise AND with OR → KILLED
            temporaryVramAddress = ((temporaryVramAddress & ADDRESS_HIGH_BYTE_CLEAR_MASK)
809
                    | ((value & ADDRESS_HIGH_BYTE_MASK) << ADDRESS_HIGH_BYTE_SHIFT))
810
                    & LOOPY_REGISTER_MASK;
811
        } else {
812 3 1. writeAddressRegister : Replaced bitwise AND with OR → KILLED
2. writeAddressRegister : Replaced bitwise OR with AND → KILLED
3. writeAddressRegister : Replaced bitwise AND with OR → KILLED
            temporaryVramAddress = (temporaryVramAddress & ADDRESS_LOW_BYTE_CLEAR_MASK) | (value & BYTE_MASK);
813
            currentVramAddress = temporaryVramAddress;
814
        }
815 1 1. writeAddressRegister : negated conditional → KILLED
        writeToggle = !writeToggle;
816
    }
817
818
    /**
819
     * Handle a $2007 read: addresses $0000-$3EFF return a buffered byte from the *previous* $2007
820
     * read (real hardware's well-known one-read-of-latency quirk), while palette addresses
821
     * ($3F00-$3FFF) return their value immediately - but still refresh the buffer with the nametable
822
     * byte "underneath" that palette mirror (real hardware physically stores nametable data at those
823
     * VRAM addresses too; the palette read just bypasses it). Both paths auto-increment
824
     * {@link #currentVramAddress}.
825
     */
826
    private int readDataRegister(){
827 1 1. readDataRegister : Replaced bitwise AND with OR → KILLED
        final int address = currentVramAddress & VRAM_ADDRESS_MASK;
828
        final int result;
829 2 1. readDataRegister : changed conditional boundary → KILLED
2. readDataRegister : negated conditional → KILLED
        if (address >= PALETTE_START_ADDRESS){
830
            result = readMemory(address);
831
            //real hardware still drives the nametable RAM address bus underneath a palette read -
832
            //$3F00-$3FFF's "underneath" address is $2F00-$2FFF (i.e. address - $1000), which
833
            //readMemory correctly routes to nametableRam since it's below PALETTE_START_ADDRESS
834 1 1. readDataRegister : Replaced integer subtraction with addition → KILLED
            readBuffer = readMemory(address - 0x1000);
835
        } else {
836
            result = readBuffer;
837
            readBuffer = readMemory(address);
838
        }
839 2 1. readDataRegister : Replaced integer addition with subtraction → KILLED
2. readDataRegister : Replaced bitwise AND with OR → KILLED
        currentVramAddress = (currentVramAddress + controlRegister.vramIncrement()) & LOOPY_REGISTER_MASK;
840 1 1. readDataRegister : replaced int return with 0 for com/rox/ppu/PPU::readDataRegister → KILLED
        return result;
841
    }
842
843
    private void writeDataRegister(final int value){
844 2 1. writeDataRegister : Replaced bitwise AND with OR → KILLED
2. writeDataRegister : removed call to com/rox/ppu/PPU::writeMemory → KILLED
        writeMemory(currentVramAddress & VRAM_ADDRESS_MASK, value);
845 2 1. writeDataRegister : Replaced bitwise AND with OR → KILLED
2. writeDataRegister : Replaced integer addition with subtraction → KILLED
        currentVramAddress = (currentVramAddress + controlRegister.vramIncrement()) & LOOPY_REGISTER_MASK;
846
    }
847
848
    /** $0000-$1FFF CHR (cartridge pattern tables), $2000-$3EFF nametables (mirrored), $3F00-$3FFF palette. */
849
    private int readMemory(final int address){
850 2 1. readMemory : changed conditional boundary → KILLED
2. readMemory : negated conditional → KILLED
        if (address < CHR_END_ADDRESS){
851 1 1. readMemory : replaced int return with 0 for com/rox/ppu/PPU::readMemory → KILLED
            return cartridge.readChr(address);
852
        }
853 2 1. readMemory : negated conditional → KILLED
2. readMemory : changed conditional boundary → KILLED
        if (address < PALETTE_START_ADDRESS){
854 1 1. readMemory : replaced int return with 0 for com/rox/ppu/PPU::readMemory → KILLED
            return nametableRam[resolveNametableIndex(address)];
855
        }
856 1 1. readMemory : replaced int return with 0 for com/rox/ppu/PPU::readMemory → KILLED
        return paletteRam[resolvePaletteIndex(address)];
857
    }
858
859
    private void writeMemory(final int address, final int value){
860 2 1. writeMemory : negated conditional → KILLED
2. writeMemory : changed conditional boundary → KILLED
        if (address < CHR_END_ADDRESS){
861 2 1. writeMemory : Replaced bitwise AND with OR → KILLED
2. writeMemory : removed call to com/rox/cartridge/Cartridge::writeChr → KILLED
            cartridge.writeChr(address, value & BYTE_MASK);
862 2 1. writeMemory : changed conditional boundary → KILLED
2. writeMemory : negated conditional → KILLED
        } else if (address < PALETTE_START_ADDRESS){
863 1 1. writeMemory : Replaced bitwise AND with OR → KILLED
            nametableRam[resolveNametableIndex(address)] = value & BYTE_MASK;
864
        } else {
865 1 1. writeMemory : Replaced bitwise AND with OR → KILLED
            paletteRam[resolvePaletteIndex(address)] = value & PALETTE_COLOR_MASK;
866
        }
867
    }
868
869
    /** Resolves a $2000-$3EFF address (already known to be below $3F00) to a physical nametable-RAM index. */
870
    private int resolveNametableIndex(final int address){
871 1 1. resolveNametableIndex : Replaced bitwise AND with OR → KILLED
        final int nametableAddress = address & 0x0FFF; //fold $3000-$3EFF's mirror of $2000-$2EFF down
872 2 1. resolveNametableIndex : Replaced bitwise AND with OR → KILLED
2. resolveNametableIndex : Replaced Shift Right with Shift Left → KILLED
        final int logicalTable = (nametableAddress >> NAMETABLE_TABLE_SHIFT) & NAMETABLE_TABLE_MASK;
873 1 1. resolveNametableIndex : Replaced bitwise AND with OR → KILLED
        final int offset = nametableAddress & NAMETABLE_OFFSET_MASK;
874
        final int physicalTable = resolvePhysicalNametable(logicalTable);
875 3 1. resolveNametableIndex : Replaced integer addition with subtraction → KILLED
2. resolveNametableIndex : Replaced integer multiplication with division → KILLED
3. resolveNametableIndex : replaced int return with 0 for com/rox/ppu/PPU::resolveNametableIndex → KILLED
        return physicalTable * 0x400 + offset;
876
    }
877
878
    public int resolvePhysicalNametable(final int logicalTable){
879 1 1. resolvePhysicalNametable : replaced int return with 0 for com/rox/ppu/PPU::resolvePhysicalNametable → KILLED
        return switch (cartridge.nametableMirroring()){
880 1 1. resolvePhysicalNametable : Replaced Shift Right with Shift Left → KILLED
            case HORIZONTAL -> logicalTable >> 1;
881 1 1. resolvePhysicalNametable : Replaced bitwise AND with OR → KILLED
            case VERTICAL -> logicalTable & 0x01;
882
            case SINGLE_SCREEN_LOWER -> 0;
883
            case SINGLE_SCREEN_UPPER -> 1;
884
        };
885
    }
886
887
    /**
888
     * Resolves a $3F00-$3FFF address to a palette-RAM index, folding in the backdrop-mirror quirk:
889
     * only $3F10/$3F14/$3F18/$3F1C mirror $3F00/$3F04/$3F08/$3F0C (every 4th entry from $3F10), not
890
     * the whole $3F10-$3F1F half of the table.
891
     */
892
    private int resolvePaletteIndex(final int address){
893 1 1. resolvePaletteIndex : Replaced bitwise AND with OR → KILLED
        final int index = address & PALETTE_INDEX_MASK;
894 4 1. resolvePaletteIndex : Replaced bitwise AND with OR → KILLED
2. resolvePaletteIndex : negated conditional → KILLED
3. resolvePaletteIndex : negated conditional → KILLED
4. resolvePaletteIndex : changed conditional boundary → KILLED
        final boolean isBackdropMirror = index >= PALETTE_BACKDROP_MIRROR_BIT && (index & 0x03) == 0;
895 3 1. resolvePaletteIndex : negated conditional → KILLED
2. resolvePaletteIndex : replaced int return with 0 for com/rox/ppu/PPU::resolvePaletteIndex → KILLED
3. resolvePaletteIndex : Replaced integer subtraction with addition → KILLED
        return isBackdropMirror ? index - PALETTE_BACKDROP_MIRROR_BIT : index;
896
    }
897
898
    /** OAM DMA ($4014): 256 bytes in one shot, wrapping from the current OAM address like OAMDATA writes do. */
899
    @Override
900
    public void writeOamDma(final int[] pageBytes){
901
        for (final int pageByte : pageBytes){
902 1 1. writeOamDma : removed call to com/rox/ppu/PPU::writeOamData → KILLED
            writeOamData(pageByte);
903
        }
904
        oamDmaPending = true;
905
    }
906
907
    /** One-shot: returns the DMA stall length (514 cycles) once per completed DMA, 0 otherwise. */
908
    public int consumeOamDmaStallCycles(){
909 1 1. consumeOamDmaStallCycles : negated conditional → KILLED
        if (oamDmaPending){
910
            oamDmaPending = false;
911 1 1. consumeOamDmaStallCycles : replaced int return with 0 for com/rox/ppu/PPU::consumeOamDmaStallCycles → KILLED
            return OAM_DMA_STALL_CYCLES;
912
        }
913
        return 0;
914
    }
915
916
    public int controlRegister(){
917 1 1. controlRegister : replaced int return with 0 for com/rox/ppu/PPU::controlRegister → KILLED
        return controlRegister.rawValue();
918
    }
919
920
    /** The decoded $2000 bits (NMI enable, pattern table selects, sprite size, nametable select, ...) - see {@link PPUControlRegister}. */
921
    public PPUControlRegister controlRegisterDecoded(){
922 1 1. controlRegisterDecoded : replaced return value with null for com/rox/ppu/PPU::controlRegisterDecoded → KILLED
        return controlRegister;
923
    }
924
925
    public int maskRegister(){
926 1 1. maskRegister : replaced int return with 0 for com/rox/ppu/PPU::maskRegister → KILLED
        return maskRegister.rawValue();
927
    }
928
929
    /** Reconstructs the original $2005 first-write byte value from the coarse and fine X scroll. */
930
    public int scrollX(){
931 4 1. scrollX : Replaced Shift Left with Shift Right → KILLED
2. scrollX : Replaced bitwise OR with AND → KILLED
3. scrollX : replaced int return with 0 for com/rox/ppu/PPU::scrollX → KILLED
4. scrollX : Replaced bitwise AND with OR → KILLED
        return ((temporaryVramAddress & COARSE_X_MASK) << 3) | fineXScroll;
932
    }
933
934
    /** Reconstructs the original $2005 second-write byte value from the coarse and fine Y scroll. */
935
    public int scrollY(){
936 7 1. scrollY : Replaced Shift Right with Shift Left → KILLED
2. scrollY : Replaced bitwise AND with OR → KILLED
3. scrollY : Replaced Shift Left with Shift Right → KILLED
4. scrollY : Replaced Shift Right with Shift Left → KILLED
5. scrollY : Replaced bitwise AND with OR → KILLED
6. scrollY : Replaced bitwise OR with AND → KILLED
7. scrollY : replaced int return with 0 for com/rox/ppu/PPU::scrollY → KILLED
        return (((temporaryVramAddress >> COARSE_Y_SHIFT) & COARSE_Y_MASK) << 3)
937
                | ((temporaryVramAddress >> FINE_Y_SHIFT) & FINE_Y_MASK);
938
    }
939
940
    public int vramAddress(){
941 1 1. vramAddress : replaced int return with 0 for com/rox/ppu/PPU::vramAddress → KILLED
        return currentVramAddress;
942
    }
943
944
    /**
945
     * The staging register ($2005/$2006 write into this, $2006's second write latches it into
946
     * {@link #currentVramAddress}).
947
     */
948
    int temporaryVramAddress(){
949 1 1. temporaryVramAddress : replaced int return with 0 for com/rox/ppu/PPU::temporaryVramAddress → KILLED
        return temporaryVramAddress;
950
    }
951
952
    public int scanline(){
953 1 1. scanline : replaced int return with 0 for com/rox/ppu/PPU::scanline → KILLED
        return scanline;
954
    }
955
956
    public int dot(){
957 1 1. dot : replaced int return with 0 for com/rox/ppu/PPU::dot → KILLED
        return dot;
958
    }
959
960
    /**
961
     * Peeks the vblank flag without the read-and-clear side effect real {@code $2002} access has via
962
     * {@link #read} - a passive observer (e.g. a debug HUD) must not be able to accidentally eat the
963
     * vblank flag/reset the write-latch out from under the emulated game's own polling.
964
     */
965
    public boolean vblankFlag(){
966 2 1. vblankFlag : replaced boolean return with false for com/rox/ppu/PPU::vblankFlag → KILLED
2. vblankFlag : replaced boolean return with true for com/rox/ppu/PPU::vblankFlag → KILLED
        return vblankFlag;
967
    }
968
969
    public int oamAddress(){
970 1 1. oamAddress : replaced int return with 0 for com/rox/ppu/PPU::oamAddress → KILLED
        return oamAddress;
971
    }
972
973
    /** Defensive copy - callers must not be able to mutate nametable RAM behind the PPU's back. */
974
    public int[] nametableSnapshot(){
975 1 1. nametableSnapshot : replaced return value with null for com/rox/ppu/PPU::nametableSnapshot → KILLED
        return nametableRam.clone();
976
    }
977
978
    /** Defensive copy - callers must not be able to mutate OAM behind the PPU's back. */
979
    public int[] oamSnapshot(){
980 1 1. oamSnapshot : replaced return value with null for com/rox/ppu/PPU::oamSnapshot → KILLED
        return oam.clone();
981
    }
982
983
    /** Defensive copy - callers must not be able to mutate the framebuffer behind the PPU's back. */
984
    public int[] framebuffer(){
985 1 1. framebuffer : replaced return value with null for com/rox/ppu/PPU::framebuffer → KILLED
        return framebuffer.clone();
986
    }
987
988
    /** {@link #framebuffer()}'s raw palette indices, converted through {@link NesPalette} to packed {@code 0xRRGGBB} colours. */
989
    public int[] rgbFramebuffer(){
990
        final int[] rgb = new int[framebuffer.length];
991 2 1. rgbFramebuffer : negated conditional → KILLED
2. rgbFramebuffer : changed conditional boundary → KILLED
        for (int i = 0; i < framebuffer.length; i++){
992
            rgb[i] = NesPalette.rgb(framebuffer[i]);
993
        }
994 1 1. rgbFramebuffer : replaced return value with null for com/rox/ppu/PPU::rgbFramebuffer → KILLED
        return rgb;
995
    }
996
997
    /**
998
     * A logical {@code $3F00-$3F1F} palette-RAM dump (32 entries), with the backdrop-mirror quirk
999
     * ({@link #resolvePaletteIndex}) already resolved - unlike the physical {@link #paletteRam} array,
1000
     * where a mirrored address (e.g. {@code $3F10}) is never itself written, this returns what a real
1001
     * read of every address in that range would actually show.
1002
     */
1003
    public int[] paletteSnapshot(){
1004
        final int[] snapshot = new int[PALETTE_SIZE];
1005 2 1. paletteSnapshot : changed conditional boundary → KILLED
2. paletteSnapshot : negated conditional → KILLED
        for (int i = 0; i < PALETTE_SIZE; i++){
1006 1 1. paletteSnapshot : Replaced integer addition with subtraction → KILLED
            snapshot[i] = paletteRam[resolvePaletteIndex(PALETTE_START_ADDRESS + i)];
1007
        }
1008 1 1. paletteSnapshot : replaced return value with null for com/rox/ppu/PPU::paletteSnapshot → KILLED
        return snapshot;
1009
    }
1010
1011
    /** Everything but the framebuffer - see {@link PpuSnapshot}. */
1012
    public PpuSnapshot snapshot(){
1013 1 1. snapshot : replaced return value with null for com/rox/ppu/PPU::snapshot → KILLED
        return new PpuSnapshot(oam.clone(), nametableRam.clone(), paletteRam.clone(),
1014
                new PpuSnapshot.Timing(dot, scanline, vblankFlag, previousNmiLine, nmiEdgePending, frameReady, oamDmaPending),
1015
                new PpuSnapshot.Registers(controlRegister.rawValue(), maskRegister.rawValue(), oamAddress, writeToggle,
1016
                        temporaryVramAddress, currentVramAddress, fineXScroll, readBuffer),
1017
                new PpuSnapshot.BackgroundPipeline(bgPatternShiftLow, bgPatternShiftHigh, bgAttributeShiftLow,
1018
                        bgAttributeShiftHigh, nextTileId, nextTilePaletteGroup, nextPatternLowByte, nextPatternHighByte),
1019
                new PpuSnapshot.SpritePipeline(secondaryOam.clone(), secondaryOamCount, secondaryOamSpriteZeroSlot,
1020
                        spriteOverflow, spriteZeroHitFlag, spritePatternLowByte.clone(), spritePatternHighByte.clone(),
1021
                        spriteAttributes.clone(), spriteXPosition.clone(), spriteIsZero.clone(), activeSpriteCount));
1022
    }
1023
1024
    /**
1025
     * Checks {@code snapshot} could be {@link #restore}d, without changing anything.
1026
     *
1027
     * @throws IllegalArgumentException if any of {@code snapshot}'s arrays is the wrong size
1028
     */
1029
    public void checkRestorable(final PpuSnapshot snapshot){
1030 1 1. checkRestorable : removed call to com/rox/ppu/PPU::requireSameSize → KILLED
        requireSameSize(snapshot.oam(), oam, "OAM");
1031 1 1. checkRestorable : removed call to com/rox/ppu/PPU::requireSameSize → KILLED
        requireSameSize(snapshot.nametableRam(), nametableRam, "nametable RAM");
1032 1 1. checkRestorable : removed call to com/rox/ppu/PPU::requireSameSize → KILLED
        requireSameSize(snapshot.paletteRam(), paletteRam, "palette RAM");
1033
        final PpuSnapshot.SpritePipeline sprites = snapshot.sprites();
1034 1 1. checkRestorable : removed call to com/rox/ppu/PPU::requireSameSize → KILLED
        requireSameSize(sprites.secondaryOam(), secondaryOam, "secondary OAM");
1035 1 1. checkRestorable : removed call to com/rox/ppu/PPU::requireSameSize → KILLED
        requireSameSize(sprites.patternLowBytes(), spritePatternLowByte, "sprite pattern low bytes");
1036 1 1. checkRestorable : removed call to com/rox/ppu/PPU::requireSameSize → KILLED
        requireSameSize(sprites.patternHighBytes(), spritePatternHighByte, "sprite pattern high bytes");
1037 1 1. checkRestorable : removed call to com/rox/ppu/PPU::requireSameSize → KILLED
        requireSameSize(sprites.attributes(), spriteAttributes, "sprite attributes");
1038 1 1. checkRestorable : removed call to com/rox/ppu/PPU::requireSameSize → KILLED
        requireSameSize(sprites.xPositions(), spriteXPosition, "sprite X positions");
1039 1 1. checkRestorable : negated conditional → KILLED
        if (sprites.isSpriteZero().length != spriteIsZero.length){
1040
            throw new IllegalArgumentException("Expected " + spriteIsZero.length + " sprite-zero slot flags, got " + sprites.isSpriteZero().length);
1041
        }
1042
    }
1043
1044
    /**
1045
     * Puts the PPU back exactly as {@code snapshot} captured it, apart from the framebuffer, which keeps
1046
     * whatever it last drew until the next frame overwrites it - all or nothing: a snapshot that fails
1047
     * {@link #checkRestorable} is rejected before anything changes.
1048
     *
1049
     * @throws IllegalArgumentException if any of {@code snapshot}'s arrays is the wrong size
1050
     */
1051
    public void restore(final PpuSnapshot snapshot){
1052 1 1. restore : removed call to com/rox/ppu/PPU::checkRestorable → KILLED
        checkRestorable(snapshot);
1053 1 1. restore : removed call to com/rox/ppu/PPU::copy → KILLED
        copy(snapshot.oam(), oam);
1054 1 1. restore : removed call to com/rox/ppu/PPU::copy → KILLED
        copy(snapshot.nametableRam(), nametableRam);
1055 1 1. restore : removed call to com/rox/ppu/PPU::copy → KILLED
        copy(snapshot.paletteRam(), paletteRam);
1056
1057
        final PpuSnapshot.Timing timing = snapshot.timing();
1058
        dot = timing.dot();
1059
        scanline = timing.scanline();
1060
        vblankFlag = timing.vblankFlag();
1061
        previousNmiLine = timing.previousNmiLine();
1062
        nmiEdgePending = timing.nmiEdgePending();
1063
        frameReady = timing.frameReady();
1064
        oamDmaPending = timing.oamDmaPending();
1065
1066
        final PpuSnapshot.Registers registers = snapshot.registers();
1067
        controlRegister = new PPUControlRegister(registers.control());
1068
        maskRegister = new PPUMaskRegister(registers.mask());
1069
        oamAddress = registers.oamAddress();
1070
        writeToggle = registers.writeToggle();
1071
        temporaryVramAddress = registers.temporaryVramAddress();
1072
        currentVramAddress = registers.currentVramAddress();
1073
        fineXScroll = registers.fineXScroll();
1074
        readBuffer = registers.readBuffer();
1075
1076
        final PpuSnapshot.BackgroundPipeline background = snapshot.background();
1077
        bgPatternShiftLow = background.patternShiftLow();
1078
        bgPatternShiftHigh = background.patternShiftHigh();
1079
        bgAttributeShiftLow = background.attributeShiftLow();
1080
        bgAttributeShiftHigh = background.attributeShiftHigh();
1081
        nextTileId = background.nextTileId();
1082
        nextTilePaletteGroup = background.nextTilePaletteGroup();
1083
        nextPatternLowByte = background.nextPatternLowByte();
1084
        nextPatternHighByte = background.nextPatternHighByte();
1085
1086
        final PpuSnapshot.SpritePipeline sprites = snapshot.sprites();
1087 1 1. restore : removed call to com/rox/ppu/PPU::copy → KILLED
        copy(sprites.secondaryOam(), secondaryOam);
1088
        secondaryOamCount = sprites.secondaryOamCount();
1089
        secondaryOamSpriteZeroSlot = sprites.secondaryOamSpriteZeroSlot();
1090
        spriteOverflow = sprites.spriteOverflow();
1091
        spriteZeroHitFlag = sprites.spriteZeroHitFlag();
1092 1 1. restore : removed call to com/rox/ppu/PPU::copy → KILLED
        copy(sprites.patternLowBytes(), spritePatternLowByte);
1093 1 1. restore : removed call to com/rox/ppu/PPU::copy → KILLED
        copy(sprites.patternHighBytes(), spritePatternHighByte);
1094 1 1. restore : removed call to com/rox/ppu/PPU::copy → KILLED
        copy(sprites.attributes(), spriteAttributes);
1095 1 1. restore : removed call to com/rox/ppu/PPU::copy → KILLED
        copy(sprites.xPositions(), spriteXPosition);
1096 1 1. restore : removed call to java/lang/System::arraycopy → KILLED
        System.arraycopy(sprites.isSpriteZero(), 0, spriteIsZero, 0, spriteIsZero.length);
1097
        activeSpriteCount = sprites.activeSpriteCount();
1098
    }
1099
1100
    private static void requireSameSize(final int[] from, final int[] into, final String what){
1101 1 1. requireSameSize : negated conditional → KILLED
        if (from.length != into.length){
1102
            throw new IllegalArgumentException("Expected " + into.length + " values of " + what + ", got " + from.length);
1103
        }
1104
    }
1105
1106
    private static void copy(final int[] from, final int[] into){
1107 1 1. copy : removed call to java/lang/System::arraycopy → KILLED
        System.arraycopy(from, 0, into, 0, into.length);
1108
    }
1109
}

Mutations

288

1.1
Location : tick
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:dotAndScanlineAdvanceTogetherAndWrapAtScanlineEnd()]
changed conditional boundary → KILLED

2.2
Location : tick
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:dotAndScanlineAdvanceTogetherAndWrapAtScanlineEnd()]
negated conditional → KILLED

289

1.1
Location : tick
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:dotAndScanlineAdvanceTogetherAndWrapAtScanlineEnd()]
removed call to com/rox/ppu/PPU::advanceDot → KILLED

294

1.1
Location : advanceDot
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:dotAndScanlineAdvanceTogetherAndWrapAtScanlineEnd()]
Replaced integer addition with subtraction → KILLED

295

1.1
Location : advanceDot
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:dotAndScanlineAdvanceTogetherAndWrapAtScanlineEnd()]
negated conditional → KILLED

2.2
Location : advanceDot
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:dotAndScanlineAdvanceTogetherAndWrapAtScanlineEnd()]
changed conditional boundary → KILLED

297

1.1
Location : advanceDot
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:dotAndScanlineAdvanceTogetherAndWrapAtScanlineEnd()]
Replaced integer addition with subtraction → KILLED

298

1.1
Location : advanceDot
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:dotAndScanlineAdvanceTogetherAndWrapAtScanlineEnd()]
negated conditional → KILLED

2.2
Location : advanceDot
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:frameReadyFiresAgainEveryFrame()]
changed conditional boundary → KILLED

302

1.1
Location : advanceDot
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:frameReadyDoesNotFireBeforeVblankStart()]
negated conditional → KILLED

2.2
Location : advanceDot
Killed by : com.rox.NESTest.[engine:junit-jupiter]/[class:com.rox.NESTest]/[method:stepFrameRunsToTheNextPresentedFrameThenFinishesTheInstruction()]
negated conditional → KILLED

303

1.1
Location : advanceDot
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:readingStatusClearsTheVblankFlag()]
removed call to com/rox/ppu/PPU::setVblankFlag → KILLED

305

1.1
Location : advanceDot
Killed by : none
negated conditional → SURVIVED
Covering tests

2.2
Location : advanceDot
Killed by : none
negated conditional → SURVIVED Covering tests

306

1.1
Location : advanceDot
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:vblankFlagClearsAutomaticallyAtPreRenderScanlineWithoutBeingRead()]
removed call to com/rox/ppu/PPU::setVblankFlag → KILLED

310

1.1
Location : advanceDot
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:coarseXIncrementWrapsAtThirtyOneAndTogglesTheNametableXBit()]
removed call to com/rox/ppu/PPU::backgroundStep → KILLED

311

1.1
Location : advanceDot
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:spriteUsesItsOwnAttributePaletteGroupNotAlwaysGroupZero()]
removed call to com/rox/ppu/PPU::spriteStep → KILLED

316

1.1
Location : consumeFrameReady
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:frameReadyDoesNotFireBeforeVblankStart()]
negated conditional → KILLED

318

1.1
Location : consumeFrameReady
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:consumeFrameReadyIsOneShot()]
replaced boolean return with false for com/rox/ppu/PPU::consumeFrameReady → KILLED

320

1.1
Location : consumeFrameReady
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:frameReadyDoesNotFireBeforeVblankStart()]
replaced boolean return with true for com/rox/ppu/PPU::consumeFrameReady → KILLED

339

1.1
Location : backgroundStep
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:spriteStillRendersOnTheLastVisibleScanlineTwoThirtyNine()]
changed conditional boundary → KILLED

2.2
Location : backgroundStep
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:coarseXIncrementWrapsAtThirtyOneAndTogglesTheNametableXBit()]
negated conditional → KILLED

3.3
Location : backgroundStep
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:verticalCopyDuringPreRenderCopiesFineYCoarseYAndTheNametableYBit()]
negated conditional → KILLED

344

1.1
Location : backgroundStep
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:tileBoundaryAtColumnEightShowsTheNextTile()]
negated conditional → KILLED

345

1.1
Location : backgroundStep
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:backgroundPixelsDecodeTileDataAtFineXZero()]
changed conditional boundary → KILLED

2.2
Location : backgroundStep
Killed by : none
changed conditional boundary → SURVIVED
Covering tests

3.3
Location : backgroundStep
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:tileBoundaryAtColumnEightShowsTheNextTile()]
negated conditional → KILLED

4.4
Location : backgroundStep
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:tileBoundaryAtColumnEightShowsTheNextTile()]
negated conditional → KILLED

5.5
Location : backgroundStep
Killed by : none
changed conditional boundary → SURVIVED Covering tests

6.6
Location : backgroundStep
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:tileBoundaryAtColumnEightShowsTheNextTile()]
negated conditional → KILLED

7.7
Location : backgroundStep
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:tileBoundaryAtColumnEightShowsTheNextTile()]
changed conditional boundary → KILLED

8.8
Location : backgroundStep
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:tileBoundaryAtColumnEightShowsTheNextTile()]
negated conditional → KILLED

347

1.1
Location : backgroundStep
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:tileBoundaryAtColumnEightShowsTheNextTile()]
negated conditional → KILLED

348

1.1
Location : backgroundStep
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:tileBoundaryAtColumnEightShowsTheNextTile()]
removed call to com/rox/ppu/PPU::shiftBackgroundShiftRegisters → KILLED

352

1.1
Location : backgroundStep
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:spriteStillRendersOnTheLastVisibleScanlineTwoThirtyNine()]
changed conditional boundary → KILLED

2.2
Location : backgroundStep
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:disablingBackgroundRenderingShowsTheBackdropEverywhere()]
changed conditional boundary → KILLED

3.3
Location : backgroundStep
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:nmiDoesNotFireWhenDisabled()]
negated conditional → KILLED

4.4
Location : backgroundStep
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:disablingBackgroundRenderingShowsTheBackdropEverywhere()]
changed conditional boundary → KILLED

5.5
Location : backgroundStep
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:vblankFlagClearsAutomaticallyAtPreRenderScanlineWithoutBeingRead()]
negated conditional → KILLED

6.6
Location : backgroundStep
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:frameReadyFiresAgainEveryFrame()]
negated conditional → KILLED

353

1.1
Location : backgroundStep
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:nmiDoesNotFireWhenDisabled()]
Replaced integer subtraction with addition → KILLED

2.2
Location : backgroundStep
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:disablingBackgroundRenderingShowsTheBackdropEverywhere()]
removed call to com/rox/ppu/PPU::drawPixel → KILLED

356

1.1
Location : backgroundStep
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:renderingDisabledEntirelyFreezesTheVRegister()]
negated conditional → KILLED

360

1.1
Location : backgroundStep
Killed by : none
changed conditional boundary → SURVIVED
Covering tests

2.2
Location : backgroundStep
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:coarseXIncrementWrapsAtThirtyOneAndTogglesTheNametableXBit()]
negated conditional → KILLED

3.3
Location : backgroundStep
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:fetchPipelineFetchesTwoTilesAheadNotTheWrongTile()]
changed conditional boundary → KILLED

4.4
Location : backgroundStep
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:coarseXIncrementWrapsAtThirtyOneAndTogglesTheNametableXBit()]
negated conditional → KILLED

361

1.1
Location : backgroundStep
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:tileBoundaryAtColumnEightShowsTheNextTile()]
negated conditional → KILLED

2.2
Location : backgroundStep
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:attributeAddressUsesTheCorrectCellNotAnAdjacentOne()]
changed conditional boundary → KILLED

3.3
Location : backgroundStep
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:tileBoundaryAtColumnEightShowsTheNextTile()]
negated conditional → KILLED

4.4
Location : backgroundStep
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:coarseXScrollFromDollarTwoZeroZeroFiveSelectsADifferentStartingTile()]
changed conditional boundary → KILLED

362

1.1
Location : backgroundStep
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:coarseXIncrementWrapsAtThirtyOneAndTogglesTheNametableXBit()]
negated conditional → KILLED

2.2
Location : backgroundStep
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:tileBoundaryAtColumnEightShowsTheNextTile()]
negated conditional → KILLED

363

1.1
Location : backgroundStep
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:coarseXIncrementWrapsAtThirtyOneAndTogglesTheNametableXBit()]
removed call to com/rox/ppu/PPU::fetchStep → KILLED

365

1.1
Location : backgroundStep
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:fineYIncrementBelowSevenLeavesCoarseYUntouched()]
negated conditional → KILLED

366

1.1
Location : backgroundStep
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:fineYIncrementBelowSevenLeavesCoarseYUntouched()]
removed call to com/rox/ppu/PPU::incrementFineY → KILLED

368

1.1
Location : backgroundStep
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:coarseXIncrementWrapsAtThirtyOneAndTogglesTheNametableXBit()]
negated conditional → KILLED

369

1.1
Location : backgroundStep
Killed by : none
removed call to com/rox/ppu/PPU::reloadShiftRegisters → SURVIVED
Covering tests

370

1.1
Location : backgroundStep
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:horizontalCopyAtDotTwoFiveSevenCopiesOnlyCoarseXAndTheNametableXBit()]
removed call to com/rox/ppu/PPU::copyHorizontalBits → KILLED

372

1.1
Location : backgroundStep
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:tileBoundaryAtColumnEightShowsTheNextTile()]
negated conditional → KILLED

373

1.1
Location : backgroundStep
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:tileBoundaryAtColumnEightShowsTheNextTile()]
removed call to com/rox/ppu/PPU::reloadShiftRegisters → KILLED

375

1.1
Location : backgroundStep
Killed by : none
negated conditional → SURVIVED
Covering tests

2.2
Location : backgroundStep
Killed by : none
changed conditional boundary → SURVIVED Covering tests

3.3
Location : backgroundStep
Killed by : none
changed conditional boundary → SURVIVED Covering tests

4.4
Location : backgroundStep
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:fineYIncrementBelowSevenLeavesCoarseYUntouched()]
negated conditional → KILLED

5.5
Location : backgroundStep
Killed by : none
negated conditional → SURVIVED Covering tests

376

1.1
Location : backgroundStep
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:verticalCopyDuringPreRenderCopiesFineYCoarseYAndTheNametableYBit()]
removed call to com/rox/ppu/PPU::copyVerticalBits → KILLED

390

1.1
Location : fetchStep
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:coarseXIncrementWrapsAtThirtyOneAndTogglesTheNametableXBit()]
Replaced integer modulus with multiplication → KILLED

2.2
Location : fetchStep
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:tileBoundaryAtColumnEightShowsTheNextTile()]
Replaced integer subtraction with addition → KILLED

392

1.1
Location : fetchStep
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:backgroundPixelsDecodeTileDataAtFineXZero()]
negated conditional → KILLED

2.2
Location : fetchStep
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:backgroundPixelsDecodeTileDataAtFineXZero()]
negated conditional → KILLED

393

1.1
Location : fetchStep
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:backgroundPixelsDecodeTileDataAtFineXZero()]
removed call to com/rox/ppu/PPU::reloadShiftRegisters → KILLED

395

1.1
Location : fetchStep
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:tileBoundaryAtColumnEightShowsTheNextTile()]
Replaced bitwise AND with OR → KILLED

2.2
Location : fetchStep
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:spriteFetchPerformsTheSameTotalChrReadsWhetherSlotsAreRealOrDummy()]
Replaced bitwise OR with AND → KILLED

400

1.1
Location : fetchStep
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:coarseXIncrementWrapsAtThirtyOneAndTogglesTheNametableXBit()]
removed call to com/rox/ppu/PPU::incrementCoarseX → KILLED

407

1.1
Location : fetchAttributePaletteGroup
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:attributeAddressUsesTheCorrectCellNotAnAdjacentOne()]
Replaced bitwise AND with OR → KILLED

2.2
Location : fetchAttributePaletteGroup
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:rgbFramebufferTracksTheUnderlyingPaletteIndices()]
Replaced bitwise OR with AND → KILLED

3.3
Location : fetchAttributePaletteGroup
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:attributeQuadrantsWithinOneAttributeCellSelectDifferentPaletteGroups()]
Replaced Shift Right with Shift Left → KILLED

4.4
Location : fetchAttributePaletteGroup
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:attributeAddressUsesTheCorrectCellNotAnAdjacentOne()]
Replaced bitwise AND with OR → KILLED

5.5
Location : fetchAttributePaletteGroup
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:rgbFramebufferTracksTheUnderlyingPaletteIndices()]
Replaced bitwise OR with AND → KILLED

6.6
Location : fetchAttributePaletteGroup
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:attributeAddressUsesTheCorrectCellNotAnAdjacentOne()]
Replaced Shift Right with Shift Left → KILLED

7.7
Location : fetchAttributePaletteGroup
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:attributeAddressUsesTheCorrectCellNotAnAdjacentOne()]
Replaced bitwise AND with OR → KILLED

8.8
Location : fetchAttributePaletteGroup
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:rgbFramebufferTracksTheUnderlyingPaletteIndices()]
Replaced bitwise OR with AND → KILLED

412

1.1
Location : fetchAttributePaletteGroup
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:attributeQuadrantsWithinOneAttributeCellSelectDifferentPaletteGroups()]
Replaced bitwise AND with OR → KILLED

413

1.1
Location : fetchAttributePaletteGroup
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:attributeQuadrantsWithinOneAttributeCellSelectDifferentPaletteGroups()]
Replaced Shift Right with Shift Left → KILLED

2.2
Location : fetchAttributePaletteGroup
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:attributeQuadrantsWithinOneAttributeCellSelectDifferentPaletteGroups()]
Replaced bitwise AND with OR → KILLED

414

1.1
Location : fetchAttributePaletteGroup
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:attributeQuadrantsWithinOneAttributeCellSelectDifferentPaletteGroups()]
Replaced bitwise AND with OR → KILLED

2.2
Location : fetchAttributePaletteGroup
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:attributeQuadrantsWithinOneAttributeCellSelectDifferentPaletteGroups()]
Replaced Shift Left with Shift Right → KILLED

3.3
Location : fetchAttributePaletteGroup
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:attributeQuadrantsWithinOneAttributeCellSelectDifferentPaletteGroups()]
Replaced bitwise AND with OR → KILLED

4.4
Location : fetchAttributePaletteGroup
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:attributeQuadrantsWithinOneAttributeCellSelectDifferentPaletteGroups()]
Replaced bitwise OR with AND → KILLED

415

1.1
Location : fetchAttributePaletteGroup
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:attributeAddressUsesTheCorrectCellNotAnAdjacentOne()]
replaced int return with 0 for com/rox/ppu/PPU::fetchAttributePaletteGroup → KILLED

2.2
Location : fetchAttributePaletteGroup
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:attributeQuadrantsWithinOneAttributeCellSelectDifferentPaletteGroups()]
Replaced Shift Right with Shift Left → KILLED

3.3
Location : fetchAttributePaletteGroup
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:tileBoundaryAtColumnEightShowsTheNextTile()]
Replaced bitwise AND with OR → KILLED

419

1.1
Location : fetchPatternByte
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:patternByteAddressUsesTheCorrectFineYRowNotAnAdjacentOne()]
Replaced Shift Right with Shift Left → KILLED

2.2
Location : fetchPatternByte
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:tileBoundaryAtColumnEightShowsTheNextTile()]
Replaced bitwise AND with OR → KILLED

420

1.1
Location : fetchPatternByte
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:frameReadyAndFramebufferAreBothCorrectWithRenderingActive()]
Replaced integer addition with subtraction → KILLED

2.2
Location : fetchPatternByte
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:tileBoundaryAtColumnEightShowsTheNextTile()]
replaced int return with 0 for com/rox/ppu/PPU::fetchPatternByte → KILLED

3.3
Location : fetchPatternByte
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:tileBoundaryAtColumnEightShowsTheNextTile()]
Replaced integer multiplication with division → KILLED

4.4
Location : fetchPatternByte
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:tileBoundaryAtColumnEightShowsTheNextTile()]
Replaced integer addition with subtraction → KILLED

5.5
Location : fetchPatternByte
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:backgroundPixelsDecodeTileDataAtFineXZero()]
Replaced integer addition with subtraction → KILLED

425

1.1
Location : reloadShiftRegisters
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:tileBoundaryAtColumnEightShowsTheNextTile()]
Replaced bitwise AND with OR → KILLED

2.2
Location : reloadShiftRegisters
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:tileBoundaryAtColumnEightShowsTheNextTile()]
Replaced bitwise OR with AND → KILLED

426

1.1
Location : reloadShiftRegisters
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:backgroundPixelsDecodeTileDataAtFineXZero()]
Replaced bitwise OR with AND → KILLED

2.2
Location : reloadShiftRegisters
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:tileBoundaryAtColumnEightShowsTheNextTile()]
Replaced bitwise AND with OR → KILLED

430

1.1
Location : reloadShiftRegisters
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:tileBoundaryAtColumnEightShowsTheNextTile()]
negated conditional → KILLED

2.2
Location : reloadShiftRegisters
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:tileBoundaryAtColumnEightShowsTheNextTile()]
Replaced bitwise AND with OR → KILLED

431

1.1
Location : reloadShiftRegisters
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:tileBoundaryAtColumnEightShowsTheNextTile()]
negated conditional → KILLED

2.2
Location : reloadShiftRegisters
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:tileBoundaryAtColumnEightShowsTheNextTile()]
Replaced bitwise AND with OR → KILLED

432

1.1
Location : reloadShiftRegisters
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:backgroundPixelsDecodeTileDataAtFineXZero()]
Replaced bitwise AND with OR → KILLED

2.2
Location : reloadShiftRegisters
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:attributeAddressUsesTheCorrectCellNotAnAdjacentOne()]
Replaced bitwise OR with AND → KILLED

433

1.1
Location : reloadShiftRegisters
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:attributeAddressUsesTheCorrectCellNotAnAdjacentOne()]
Replaced bitwise OR with AND → KILLED

2.2
Location : reloadShiftRegisters
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:backgroundPixelsDecodeTileDataAtFineXZero()]
Replaced bitwise AND with OR → KILLED

437

1.1
Location : shiftBackgroundShiftRegisters
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:tileBoundaryAtColumnEightShowsTheNextTile()]
Replaced bitwise AND with OR → KILLED

2.2
Location : shiftBackgroundShiftRegisters
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:tileBoundaryAtColumnEightShowsTheNextTile()]
Replaced Shift Left with Shift Right → KILLED

438

1.1
Location : shiftBackgroundShiftRegisters
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:tileBoundaryAtColumnEightShowsTheNextTile()]
Replaced bitwise AND with OR → KILLED

2.2
Location : shiftBackgroundShiftRegisters
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:backgroundPixelsDecodeTileDataAtFineXZero()]
Replaced Shift Left with Shift Right → KILLED

439

1.1
Location : shiftBackgroundShiftRegisters
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:tileBoundaryAtColumnEightShowsTheNextTile()]
Replaced bitwise AND with OR → KILLED

2.2
Location : shiftBackgroundShiftRegisters
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:attributeAddressUsesTheCorrectCellNotAnAdjacentOne()]
Replaced Shift Left with Shift Right → KILLED

440

1.1
Location : shiftBackgroundShiftRegisters
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:attributeAddressUsesTheCorrectCellNotAnAdjacentOne()]
Replaced Shift Left with Shift Right → KILLED

2.2
Location : shiftBackgroundShiftRegisters
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:tileBoundaryAtColumnEightShowsTheNextTile()]
Replaced bitwise AND with OR → KILLED

445

1.1
Location : incrementCoarseX
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:coarseXIncrementWrapsAtThirtyOneAndTogglesTheNametableXBit()]
negated conditional → KILLED

2.2
Location : incrementCoarseX
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:fineYIncrementBelowSevenLeavesCoarseYUntouched()]
Replaced bitwise AND with OR → KILLED

446

1.1
Location : incrementCoarseX
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:coarseXIncrementWrapsAtThirtyOneAndTogglesTheNametableXBit()]
Replaced XOR with AND → KILLED

2.2
Location : incrementCoarseX
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:coarseXIncrementWrapsAtThirtyOneAndTogglesTheNametableXBit()]
Replaced bitwise AND with OR → KILLED

448

1.1
Location : incrementCoarseX
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:fineYIncrementBelowSevenLeavesCoarseYUntouched()]
Replaced integer addition with subtraction → KILLED

2.2
Location : incrementCoarseX
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:fineYIncrementBelowSevenLeavesCoarseYUntouched()]
Replaced bitwise AND with OR → KILLED

460

1.1
Location : incrementFineY
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:fineYIncrementBelowSevenLeavesCoarseYUntouched()]
negated conditional → KILLED

2.2
Location : incrementFineY
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:fineYWrapAtCoarseYThirtyOneDoesNotToggleTheNametableYBit()]
Replaced bitwise AND with OR → KILLED

461

1.1
Location : incrementFineY
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:fineYIncrementBelowSevenLeavesCoarseYUntouched()]
Replaced integer addition with subtraction → KILLED

2.2
Location : incrementFineY
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:fineYIncrementBelowSevenLeavesCoarseYUntouched()]
Replaced bitwise AND with OR → KILLED

464

1.1
Location : incrementFineY
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:fineYWrapAtCoarseYThirtyOneDoesNotToggleTheNametableYBit()]
Replaced bitwise AND with OR → KILLED

465

1.1
Location : incrementFineY
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:fineYWrapAtCoarseYThirtyOneDoesNotToggleTheNametableYBit()]
Replaced Shift Right with Shift Left → KILLED

2.2
Location : incrementFineY
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:fineYWrapAtCoarseYThirtyOneDoesNotToggleTheNametableYBit()]
Replaced bitwise AND with OR → KILLED

466

1.1
Location : incrementFineY
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:fineYWrapAtCoarseYThirtyOneDoesNotToggleTheNametableYBit()]
negated conditional → KILLED

468

1.1
Location : incrementFineY
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:fineYWrapAtCoarseYTwentyNineTogglesTheNametableYBit()]
Replaced XOR with AND → KILLED

469

1.1
Location : incrementFineY
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:fineYWrapAtAMidRangeCoarseYJustIncrementsCoarseY()]
negated conditional → KILLED

472

1.1
Location : incrementFineY
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:fineYWrapAtAMidRangeCoarseYJustIncrementsCoarseY()]
Changed increment from 1 to -1 → KILLED

474

1.1
Location : incrementFineY
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:fineYWrapAtCoarseYThirtyOneDoesNotToggleTheNametableYBit()]
Replaced bitwise AND with OR → KILLED

2.2
Location : incrementFineY
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:fineYWrapAtAMidRangeCoarseYJustIncrementsCoarseY()]
Replaced Shift Left with Shift Right → KILLED

3.3
Location : incrementFineY
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:fineYWrapAtAMidRangeCoarseYJustIncrementsCoarseY()]
Replaced bitwise OR with AND → KILLED

4.4
Location : incrementFineY
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:fineYWrapAtCoarseYThirtyOneDoesNotToggleTheNametableYBit()]
Replaced bitwise AND with OR → KILLED

479

1.1
Location : copyHorizontalBits
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:fineYIncrementBelowSevenLeavesCoarseYUntouched()]
Replaced bitwise OR with AND → KILLED

2.2
Location : copyHorizontalBits
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:fineYWrapAtCoarseYThirtyOneDoesNotToggleTheNametableYBit()]
Replaced bitwise AND with OR → KILLED

3.3
Location : copyHorizontalBits
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:fineYIncrementBelowSevenLeavesCoarseYUntouched()]
Replaced bitwise AND with OR → KILLED

4.4
Location : copyHorizontalBits
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:fineYIncrementBelowSevenLeavesCoarseYUntouched()]
Replaced bitwise AND with OR → KILLED

485

1.1
Location : copyVerticalBits
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:verticalCopyDuringPreRenderCopiesFineYCoarseYAndTheNametableYBit()]
Replaced bitwise AND with OR → KILLED

2.2
Location : copyVerticalBits
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:verticalCopyDuringPreRenderCopiesFineYCoarseYAndTheNametableYBit()]
Replaced bitwise OR with AND → KILLED

3.3
Location : copyVerticalBits
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:verticalCopyDuringPreRenderCopiesFineYCoarseYAndTheNametableYBit()]
Replaced bitwise AND with OR → KILLED

4.4
Location : copyVerticalBits
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:verticalCopyDuringPreRenderCopiesFineYCoarseYAndTheNametableYBit()]
Replaced bitwise AND with OR → KILLED

490

1.1
Location : renderingEnabled
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:coarseXIncrementWrapsAtThirtyOneAndTogglesTheNametableXBit()]
replaced boolean return with false for com/rox/ppu/PPU::renderingEnabled → KILLED

2.2
Location : renderingEnabled
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:renderingDisabledEntirelyFreezesTheVRegister()]
replaced boolean return with true for com/rox/ppu/PPU::renderingEnabled → KILLED

501

1.1
Location : spriteStep
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:spriteNeverAppearsOnScanlineZero()]
negated conditional → KILLED

2.2
Location : spriteStep
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:spriteUsesItsOwnAttributePaletteGroupNotAlwaysGroupZero()]
negated conditional → KILLED

3.3
Location : spriteStep
Killed by : none
changed conditional boundary → SURVIVED
Covering tests

504

1.1
Location : spriteStep
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:spriteUsesItsOwnAttributePaletteGroupNotAlwaysGroupZero()]
negated conditional → KILLED

507

1.1
Location : spriteStep
Killed by : none
negated conditional → SURVIVED
Covering tests

508

1.1
Location : spriteStep
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:spriteUsesItsOwnAttributePaletteGroupNotAlwaysGroupZero()]
removed call to com/rox/ppu/PPU::evaluateSpritesForNextScanline → KILLED

510

1.1
Location : spriteStep
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:spriteFetchPerformsTheSameTotalChrReadsWhetherSlotsAreRealOrDummy()]
negated conditional → KILLED

511

1.1
Location : spriteStep
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:spriteUsesItsOwnAttributePaletteGroupNotAlwaysGroupZero()]
removed call to com/rox/ppu/PPU::fetchSpritesForNextScanline → KILLED

532

1.1
Location : evaluateSpritesForNextScanline
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:spriteUsesItsOwnAttributePaletteGroupNotAlwaysGroupZero()]
Replaced integer addition with subtraction → KILLED

2.2
Location : evaluateSpritesForNextScanline
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:spriteUsesItsOwnAttributePaletteGroupNotAlwaysGroupZero()]
negated conditional → KILLED

533

1.1
Location : evaluateSpritesForNextScanline
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:tallSpriteStacksTwoTilesVertically()]
negated conditional → KILLED

537

1.1
Location : evaluateSpritesForNextScanline
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:fineYIncrementBelowSevenLeavesCoarseYUntouched()]
changed conditional boundary → KILLED

2.2
Location : evaluateSpritesForNextScanline
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:spriteUsesItsOwnAttributePaletteGroupNotAlwaysGroupZero()]
negated conditional → KILLED

538

1.1
Location : evaluateSpritesForNextScanline
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:overflowFlagStaysClearWithEightOrFewerSpritesInRange()]
Replaced integer multiplication with division → KILLED

539

1.1
Location : evaluateSpritesForNextScanline
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:spriteOnlyAppearsForItsOwnEightRowRange()]
Replaced integer subtraction with addition → KILLED

2.2
Location : evaluateSpritesForNextScanline
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:spriteOnlyAppearsForItsOwnEightRowRange()]
Replaced integer subtraction with addition → KILLED

540

1.1
Location : evaluateSpritesForNextScanline
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:spriteUsesItsOwnAttributePaletteGroupNotAlwaysGroupZero()]
negated conditional → KILLED

2.2
Location : evaluateSpritesForNextScanline
Killed by : none
changed conditional boundary → SURVIVED
Covering tests

3.3
Location : evaluateSpritesForNextScanline
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:spriteUsesItsOwnAttributePaletteGroupNotAlwaysGroupZero()]
changed conditional boundary → KILLED

4.4
Location : evaluateSpritesForNextScanline
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:spriteUsesItsOwnAttributePaletteGroupNotAlwaysGroupZero()]
negated conditional → KILLED

543

1.1
Location : evaluateSpritesForNextScanline
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:fineYIncrementBelowSevenLeavesCoarseYUntouched()]
changed conditional boundary → KILLED

2.2
Location : evaluateSpritesForNextScanline
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:spriteUsesItsOwnAttributePaletteGroupNotAlwaysGroupZero()]
negated conditional → KILLED

544

1.1
Location : evaluateSpritesForNextScanline
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:lowerOamIndexWinsPriorityOverAHigherIndexAtTheSameSlotPosition()]
Replaced integer multiplication with division → KILLED

546

1.1
Location : evaluateSpritesForNextScanline
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:fineYIncrementBelowSevenLeavesCoarseYUntouched()]
Replaced integer addition with subtraction → KILLED

2.2
Location : evaluateSpritesForNextScanline
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:fineYIncrementBelowSevenLeavesCoarseYUntouched()]
Replaced integer addition with subtraction → KILLED

547

1.1
Location : evaluateSpritesForNextScanline
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:fineYIncrementBelowSevenLeavesCoarseYUntouched()]
Replaced integer addition with subtraction → KILLED

2.2
Location : evaluateSpritesForNextScanline
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:fineYIncrementBelowSevenLeavesCoarseYUntouched()]
Replaced integer addition with subtraction → KILLED

548

1.1
Location : evaluateSpritesForNextScanline
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:fineYIncrementBelowSevenLeavesCoarseYUntouched()]
Replaced integer addition with subtraction → KILLED

2.2
Location : evaluateSpritesForNextScanline
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:fineYIncrementBelowSevenLeavesCoarseYUntouched()]
Replaced integer addition with subtraction → KILLED

549

1.1
Location : evaluateSpritesForNextScanline
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:spriteZeroHitFlagSetsOnOverlapOfOpaqueSpriteAndBackground()]
negated conditional → KILLED

552

1.1
Location : evaluateSpritesForNextScanline
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:fineYIncrementBelowSevenLeavesCoarseYUntouched()]
Changed increment from 1 to -1 → KILLED

559

1.1
Location : evaluateSpritesForNextScanline
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:overflowFlagStaysClearWithEightOrFewerSpritesInRange()]
negated conditional → KILLED

572

1.1
Location : fetchSpritesForNextScanline
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:spriteUsesItsOwnAttributePaletteGroupNotAlwaysGroupZero()]
Replaced integer addition with subtraction → KILLED

2.2
Location : fetchSpritesForNextScanline
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:spriteUsesItsOwnAttributePaletteGroupNotAlwaysGroupZero()]
negated conditional → KILLED

574

1.1
Location : fetchSpritesForNextScanline
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:verticalFlipReversesTheRowOrder()]
negated conditional → KILLED

575

1.1
Location : fetchSpritesForNextScanline
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:spriteFetchPerformsTheSameTotalChrReadsWhetherSlotsAreRealOrDummy()]
negated conditional → KILLED

2.2
Location : fetchSpritesForNextScanline
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:fineYIncrementBelowSevenLeavesCoarseYUntouched()]
changed conditional boundary → KILLED

576

1.1
Location : fetchSpritesForNextScanline
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:onlyEightSpritesRenderPerScanlineAndTheNinthSetsOverflow()]
Replaced integer multiplication with division → KILLED

578

1.1
Location : fetchSpritesForNextScanline
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:fineYIncrementBelowSevenLeavesCoarseYUntouched()]
Replaced integer addition with subtraction → KILLED

579

1.1
Location : fetchSpritesForNextScanline
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:fineYIncrementBelowSevenLeavesCoarseYUntouched()]
Replaced integer addition with subtraction → KILLED

580

1.1
Location : fetchSpritesForNextScanline
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:unflippedSpriteKeepsThePixelPatternAsFetched()]
Replaced bitwise AND with OR → KILLED

2.2
Location : fetchSpritesForNextScanline
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:unflippedSpriteKeepsThePixelPatternAsFetched()]
negated conditional → KILLED

581

1.1
Location : fetchSpritesForNextScanline
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:unflippedSpriteKeepsThePixelPatternAsFetched()]
negated conditional → KILLED

2.2
Location : fetchSpritesForNextScanline
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:unflippedSpriteKeepsThePixelPatternAsFetched()]
Replaced bitwise AND with OR → KILLED

583

1.1
Location : fetchSpritesForNextScanline
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:unflippedSpriteKeepsThePixelPatternAsFetched()]
Replaced integer subtraction with addition → KILLED

2.2
Location : fetchSpritesForNextScanline
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:spriteOnlyAppearsForItsOwnEightRowRange()]
Replaced integer subtraction with addition → KILLED

584

1.1
Location : fetchSpritesForNextScanline
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:unflippedSpriteKeepsThePixelPatternAsFetched()]
negated conditional → KILLED

585

1.1
Location : fetchSpritesForNextScanline
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:verticalFlipReversesTheRowOrder()]
Replaced integer subtraction with addition → KILLED

2.2
Location : fetchSpritesForNextScanline
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:verticalFlipReversesTheRowOrder()]
Replaced integer subtraction with addition → KILLED

589

1.1
Location : fetchSpritesForNextScanline
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:tallSpritePatternTableComesFromTheTileIndexLowBitNotPpuctrl()]
negated conditional → KILLED

590

1.1
Location : fetchSpritesForNextScanline
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:tallSpritePatternTableComesFromTheTileIndexLowBitNotPpuctrl()]
negated conditional → KILLED

591

1.1
Location : fetchSpritesForNextScanline
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:tallSpritePatternTableComesFromTheTileIndexLowBitNotPpuctrl()]
Replaced bitwise AND with OR → KILLED

592

1.1
Location : fetchSpritesForNextScanline
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:tallSpriteStacksTwoTilesVertically()]
changed conditional boundary → KILLED

2.2
Location : fetchSpritesForNextScanline
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:tallSpritePatternTableComesFromTheTileIndexLowBitNotPpuctrl()]
negated conditional → KILLED

594

1.1
Location : fetchSpritesForNextScanline
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:tallSpriteStacksTwoTilesVertically()]
Changed increment from -8 to 8 → KILLED

603

1.1
Location : fetchSpritesForNextScanline
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:spriteOnlyAppearsForItsOwnEightRowRange()]
Replaced integer addition with subtraction → KILLED

2.2
Location : fetchSpritesForNextScanline
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:tallSpritePatternTableComesFromTheTileIndexLowBitNotPpuctrl()]
Replaced integer addition with subtraction → KILLED

3.3
Location : fetchSpritesForNextScanline
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:tallSpritePatternTableComesFromTheTileIndexLowBitNotPpuctrl()]
Replaced integer multiplication with division → KILLED

604

1.1
Location : fetchSpritesForNextScanline
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:verticalFlipReversesTheRowOrder()]
Replaced integer addition with subtraction → KILLED

2.2
Location : fetchSpritesForNextScanline
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:tallSpriteStacksTwoTilesVertically()]
Replaced integer multiplication with division → KILLED

3.3
Location : fetchSpritesForNextScanline
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:spriteOnlyAppearsForItsOwnEightRowRange()]
Replaced integer addition with subtraction → KILLED

4.4
Location : fetchSpritesForNextScanline
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:tallSpriteStacksTwoTilesVertically()]
Replaced integer addition with subtraction → KILLED

605

1.1
Location : fetchSpritesForNextScanline
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:unflippedSpriteKeepsThePixelPatternAsFetched()]
negated conditional → KILLED

613

1.1
Location : fetchSpritesForNextScanline
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:fineYIncrementBelowSevenLeavesCoarseYUntouched()]
Replaced integer addition with subtraction → KILLED

614

1.1
Location : fetchSpritesForNextScanline
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:spriteZeroHitFlagSetsOnOverlapOfOpaqueSpriteAndBackground()]
negated conditional → KILLED

623

1.1
Location : fetchSpritesForNextScanline
Killed by : none
negated conditional → TIMED_OUT

2.2
Location : fetchSpritesForNextScanline
Killed by : none
changed conditional boundary → SURVIVED
Covering tests

624

1.1
Location : fetchSpritesForNextScanline
Killed by : none
negated conditional → SURVIVED
Covering tests

625

1.1
Location : fetchSpritesForNextScanline
Killed by : none
negated conditional → SURVIVED
Covering tests

626

1.1
Location : fetchSpritesForNextScanline
Killed by : none
Replaced integer addition with subtraction → SURVIVED
Covering tests

2.2
Location : fetchSpritesForNextScanline
Killed by : none
Replaced integer multiplication with division → SURVIVED Covering tests

627

1.1
Location : fetchSpritesForNextScanline
Killed by : none
Replaced integer addition with subtraction → SURVIVED
Covering tests

2.2
Location : fetchSpritesForNextScanline
Killed by : none
Replaced integer multiplication with division → SURVIVED Covering tests

3.3
Location : fetchSpritesForNextScanline
Killed by : none
Replaced integer addition with subtraction → SURVIVED Covering tests

636

1.1
Location : reverseBits
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:horizontalFlipReversesThePixelOrder()]
negated conditional → KILLED

2.2
Location : reverseBits
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:horizontalFlipReversesThePixelOrder()]
changed conditional boundary → KILLED

637

1.1
Location : reverseBits
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:horizontalFlipReversesThePixelOrder()]
Replaced Shift Left with Shift Right → KILLED

2.2
Location : reverseBits
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:horizontalFlipReversesThePixelOrder()]
Replaced bitwise AND with OR → KILLED

3.3
Location : reverseBits
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:horizontalFlipReversesThePixelOrder()]
Replaced bitwise OR with AND → KILLED

638

1.1
Location : reverseBits
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:horizontalFlipReversesThePixelOrder()]
Replaced Shift Right with Shift Left → KILLED

640

1.1
Location : reverseBits
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:horizontalFlipReversesThePixelOrder()]
replaced int return with 0 for com/rox/ppu/PPU::reverseBits → KILLED

653

1.1
Location : drawPixel
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:leftEightPixelClipHidesTheBackgroundOnlyInThatRegion()]
negated conditional → KILLED

2.2
Location : drawPixel
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:tileBoundaryAtColumnEightShowsTheNextTile()]
negated conditional → KILLED

3.3
Location : drawPixel
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:backgroundPixelsDecodeTileDataAtFineXZero()]
negated conditional → KILLED

4.4
Location : drawPixel
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:leftEightPixelClipHidesTheBackgroundOnlyInThatRegion()]
changed conditional boundary → KILLED

657

1.1
Location : drawPixel
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:renderingIsEnabledByEitherShowBackgroundOrShowSpritesNotJustBackground()]
negated conditional → KILLED

658

1.1
Location : drawPixel
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:fineXScrollShiftsTheTileBoundaryEarlierAcrossTiles()]
Replaced Shift Right with Shift Left → KILLED

659

1.1
Location : drawPixel
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:backgroundPixelsDecodeTileDataAtFineXZero()]
negated conditional → KILLED

2.2
Location : drawPixel
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:backgroundPixelsDecodeTileDataAtFineXZero()]
Replaced bitwise AND with OR → KILLED

660

1.1
Location : drawPixel
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:backgroundPixelsDecodeTileDataAtFineXZero()]
Replaced bitwise AND with OR → KILLED

2.2
Location : drawPixel
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:backgroundPixelsDecodeTileDataAtFineXZero()]
negated conditional → KILLED

3.3
Location : drawPixel
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:backgroundPixelsDecodeTileDataAtFineXZero()]
Replaced bitwise OR with AND → KILLED

661

1.1
Location : drawPixel
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:backgroundPixelsDecodeTileDataAtFineXZero()]
negated conditional → KILLED

662

1.1
Location : drawPixel
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:backgroundPixelsDecodeTileDataAtFineXZero()]
negated conditional → KILLED

2.2
Location : drawPixel
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:backgroundPixelsDecodeTileDataAtFineXZero()]
Replaced bitwise AND with OR → KILLED

663

1.1
Location : drawPixel
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:backgroundPixelsDecodeTileDataAtFineXZero()]
Replaced bitwise AND with OR → KILLED

2.2
Location : drawPixel
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:backgroundPixelsDecodeTileDataAtFineXZero()]
negated conditional → KILLED

3.3
Location : drawPixel
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:attributeAddressUsesTheCorrectCellNotAnAdjacentOne()]
Replaced bitwise OR with AND → KILLED

664

1.1
Location : drawPixel
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:attributeAddressUsesTheCorrectCellNotAnAdjacentOne()]
Replaced Shift Left with Shift Right → KILLED

2.2
Location : drawPixel
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:attributeAddressUsesTheCorrectCellNotAnAdjacentOne()]
Replaced integer addition with subtraction → KILLED

3.3
Location : drawPixel
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:backgroundPixelsDecodeTileDataAtFineXZero()]
Replaced integer addition with subtraction → KILLED

668

1.1
Location : drawPixel
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:spriteUsesItsOwnAttributePaletteGroupNotAlwaysGroupZero()]
negated conditional → KILLED

2.2
Location : drawPixel
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:spritesInTheLeftEightPixelsAreClippedWhenTheirShowLeftBitIsOff()]
negated conditional → KILLED

3.3
Location : drawPixel
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:spriteUsesItsOwnAttributePaletteGroupNotAlwaysGroupZero()]
negated conditional → KILLED

4.4
Location : drawPixel
Killed by : none
changed conditional boundary → SURVIVED
Covering tests

669

1.1
Location : drawPixel
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:spriteUsesItsOwnAttributePaletteGroupNotAlwaysGroupZero()]
negated conditional → KILLED

670

1.1
Location : drawPixel
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:spriteFetchPerformsTheSameTotalChrReadsWhetherSlotsAreRealOrDummy()]
negated conditional → KILLED

2.2
Location : drawPixel
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:spriteFetchPerformsTheSameTotalChrReadsWhetherSlotsAreRealOrDummy()]
changed conditional boundary → KILLED

671

1.1
Location : drawPixel
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:spriteOnlyAppearsForItsOwnEightRowRange()]
Replaced integer subtraction with addition → KILLED

672

1.1
Location : drawPixel
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:horizontalFlipReversesThePixelOrder()]
changed conditional boundary → KILLED

2.2
Location : drawPixel
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:spriteUsesItsOwnAttributePaletteGroupNotAlwaysGroupZero()]
changed conditional boundary → KILLED

3.3
Location : drawPixel
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:spriteUsesItsOwnAttributePaletteGroupNotAlwaysGroupZero()]
negated conditional → KILLED

4.4
Location : drawPixel
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:spriteUsesItsOwnAttributePaletteGroupNotAlwaysGroupZero()]
negated conditional → KILLED

675

1.1
Location : drawPixel
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:unflippedSpriteKeepsThePixelPatternAsFetched()]
Replaced Shift Right with Shift Left → KILLED

676

1.1
Location : drawPixel
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:spriteUsesItsOwnAttributePaletteGroupNotAlwaysGroupZero()]
Replaced bitwise AND with OR → KILLED

2.2
Location : drawPixel
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:spriteUsesItsOwnAttributePaletteGroupNotAlwaysGroupZero()]
negated conditional → KILLED

677

1.1
Location : drawPixel
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:spriteUsesItsOwnAttributePaletteGroupNotAlwaysGroupZero()]
Replaced bitwise OR with AND → KILLED

2.2
Location : drawPixel
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:spriteUsesItsOwnAttributePaletteGroupNotAlwaysGroupZero()]
negated conditional → KILLED

3.3
Location : drawPixel
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:unflippedSpriteKeepsThePixelPatternAsFetched()]
Replaced bitwise AND with OR → KILLED

678

1.1
Location : drawPixel
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:spriteUsesItsOwnAttributePaletteGroupNotAlwaysGroupZero()]
negated conditional → KILLED

681

1.1
Location : drawPixel
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:spriteZeroHitFlagSetsOnOverlapOfOpaqueSpriteAndBackground()]
negated conditional → KILLED

2.2
Location : drawPixel
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:spriteZeroHitFlagDoesNotSetWithoutBothBackgroundAndSpritesEnabled()]
negated conditional → KILLED

3.3
Location : drawPixel
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:spriteZeroHitFlagSetsOnOverlapOfOpaqueSpriteAndBackground()]
negated conditional → KILLED

684

1.1
Location : drawPixel
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:behindPrioritySpriteHidesBehindAnOpaqueBackgroundPixel()]
negated conditional → KILLED

2.2
Location : drawPixel
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:frontPrioritySpriteDrawsOverAnOpaqueBackgroundPixel()]
Replaced bitwise AND with OR → KILLED

685

1.1
Location : drawPixel
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:behindPrioritySpriteStillShowsOverATransparentBackgroundPixel()]
negated conditional → KILLED

2.2
Location : drawPixel
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:behindPrioritySpriteHidesBehindAnOpaqueBackgroundPixel()]
negated conditional → KILLED

686

1.1
Location : drawPixel
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:spriteUsesItsOwnAttributePaletteGroupNotAlwaysGroupZero()]
Replaced bitwise AND with OR → KILLED

687

1.1
Location : drawPixel
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:spriteUsesItsOwnAttributePaletteGroupNotAlwaysGroupZero()]
Replaced Shift Left with Shift Right → KILLED

2.2
Location : drawPixel
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:spriteUsesItsOwnAttributePaletteGroupNotAlwaysGroupZero()]
Replaced integer addition with subtraction → KILLED

3.3
Location : drawPixel
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:spriteUsesItsOwnAttributePaletteGroupNotAlwaysGroupZero()]
Replaced integer addition with subtraction → KILLED

693

1.1
Location : drawPixel
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:disablingBackgroundRenderingShowsTheBackdropEverywhere()]
Replaced bitwise AND with OR → KILLED

2.2
Location : drawPixel
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:backgroundPixelsDecodeTileDataAtFineXZero()]
Replaced integer multiplication with division → KILLED

3.3
Location : drawPixel
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:renderingDisabledEntirelyFreezesTheVRegister()]
Replaced integer addition with subtraction → KILLED

698

1.1
Location : setVblankFlag
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:registersMirrorEveryEightBytes()]
removed call to com/rox/ppu/PPU::updateNmiLine → KILLED

703

1.1
Location : updateNmiLine
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:nmiDoesNotFireWhenDisabled()]
negated conditional → KILLED

2.2
Location : updateNmiLine
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:enablingNmiWhileAlreadyInVblankFiresImmediately()]
negated conditional → KILLED

704

1.1
Location : updateNmiLine
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:registersMirrorEveryEightBytes()]
negated conditional → KILLED

2.2
Location : updateNmiLine
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:nmiDoesNotFireWhenDisabled()]
negated conditional → KILLED

712

1.1
Location : consumeNmiEdge
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:nmiDoesNotFireWhenDisabled()]
negated conditional → KILLED

714

1.1
Location : consumeNmiEdge
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:registersMirrorEveryEightBytes()]
replaced boolean return with false for com/rox/ppu/PPU::consumeNmiEdge → KILLED

716

1.1
Location : consumeNmiEdge
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:nmiDoesNotFireWhenDisabled()]
replaced boolean return with true for com/rox/ppu/PPU::consumeNmiEdge → KILLED

721

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

731

1.1
Location : write
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:maskRegisterIsCapturedButOtherwiseUnused()]
Replaced bitwise AND with OR → KILLED

732

1.1
Location : write
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:ctrlWriteLatchesNametableSelectBitsIntoT()]
removed call to com/rox/ppu/PPU::writeControlRegister → KILLED

734

1.1
Location : write
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:oamSnapshotReflectsWrittenData()]
Replaced bitwise AND with OR → KILLED

735

1.1
Location : write
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:oamSnapshotReflectsWrittenData()]
removed call to com/rox/ppu/PPU::writeOamData → KILLED

736

1.1
Location : write
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:scrollAndAddressRegistersShareTheSameWriteLatch()]
removed call to com/rox/ppu/PPU::writeScrollRegister → KILLED

737

1.1
Location : write
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:addressFirstWriteClearsTheUnusedFifteenthBitOfT()]
removed call to com/rox/ppu/PPU::writeAddressRegister → KILLED

738

1.1
Location : write
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:vramIncrementDefaultsToOne()]
removed call to com/rox/ppu/PPU::writeDataRegister → KILLED

752

1.1
Location : writeControlRegister
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:ctrlWriteOnlyLatchesTheLowTwoNametableSelectBitsFromValue()]
Replaced bitwise AND with OR → KILLED

753

1.1
Location : writeControlRegister
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:ctrlWriteLatchesNametableSelectBitsIntoT()]
Replaced bitwise OR with AND → KILLED

2.2
Location : writeControlRegister
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:ctrlWriteLatchesNametableSelectBitsIntoT()]
Replaced Shift Left with Shift Right → KILLED

754

1.1
Location : writeControlRegister
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:disablingNmiThenReenablingDuringTheSameVblankFiresAgain()]
removed call to com/rox/ppu/PPU::updateNmiLine → KILLED

770

1.1
Location : readStatusRegister
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:vblankFlagStartsClear()]
negated conditional → KILLED

771

1.1
Location : readStatusRegister
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:spriteZeroHitFlagDoesNotSetWithoutBothBackgroundAndSpritesEnabled()]
negated conditional → KILLED

2.2
Location : readStatusRegister
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:readingStatusClearsTheVblankFlag()]
Replaced bitwise OR with AND → KILLED

772

1.1
Location : readStatusRegister
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:overflowFlagStaysClearWithEightOrFewerSpritesInRange()]
negated conditional → KILLED

2.2
Location : readStatusRegister
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:readingStatusClearsTheVblankFlag()]
Replaced bitwise OR with AND → KILLED

775

1.1
Location : readStatusRegister
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:readingStatusClearsTheVblankFlag()]
replaced int return with 0 for com/rox/ppu/PPU::readStatusRegister → KILLED

779

1.1
Location : writeOamData
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:oamSnapshotReflectsWrittenData()]
Replaced bitwise AND with OR → KILLED

780

1.1
Location : writeOamData
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:oamAddressAndDataRoundTripWithAutoIncrementOnWriteOnly()]
Replaced integer addition with subtraction → KILLED

2.2
Location : writeOamData
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:oamAddressAndDataRoundTripWithAutoIncrementOnWriteOnly()]
Replaced bitwise AND with OR → KILLED

790

1.1
Location : writeScrollRegister
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:scrollAndAddressRegistersShareTheSameWriteLatch()]
negated conditional → KILLED

791

1.1
Location : writeScrollRegister
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:scrollRegisterCapturesXThenYInOrder()]
Replaced bitwise AND with OR → KILLED

792

1.1
Location : writeScrollRegister
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:scrollRegisterCapturesXThenYInOrder()]
Replaced Shift Right with Shift Left → KILLED

2.2
Location : writeScrollRegister
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:scrollFirstWriteClearsAnyPriorCoarseXBitsOfT()]
Replaced bitwise AND with OR → KILLED

3.3
Location : writeScrollRegister
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:scrollRegisterCapturesXThenYInOrder()]
Replaced bitwise OR with AND → KILLED

794

1.1
Location : writeScrollRegister
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:scrollAndAddressRegistersShareTheSameWriteLatch()]
Replaced bitwise AND with OR → KILLED

2.2
Location : writeScrollRegister
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:scrollAndAddressRegistersShareTheSameWriteLatch()]
Replaced bitwise OR with AND → KILLED

3.3
Location : writeScrollRegister
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:scrollAndAddressRegistersShareTheSameWriteLatch()]
Replaced Shift Left with Shift Right → KILLED

4.4
Location : writeScrollRegister
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:scrollAndAddressRegistersShareTheSameWriteLatch()]
Replaced bitwise AND with OR → KILLED

795

1.1
Location : writeScrollRegister
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:scrollAndAddressRegistersShareTheSameWriteLatch()]
Replaced bitwise AND with OR → KILLED

2.2
Location : writeScrollRegister
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:scrollAndAddressRegistersShareTheSameWriteLatch()]
Replaced Shift Right with Shift Left → KILLED

3.3
Location : writeScrollRegister
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:scrollAndAddressRegistersShareTheSameWriteLatch()]
Replaced bitwise OR with AND → KILLED

4.4
Location : writeScrollRegister
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:scrollAndAddressRegistersShareTheSameWriteLatch()]
Replaced Shift Left with Shift Right → KILLED

797

1.1
Location : writeScrollRegister
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:scrollRegisterCapturesXThenYInOrder()]
negated conditional → KILLED

807

1.1
Location : writeAddressRegister
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:addressFirstWriteClearsTheUnusedFifteenthBitOfT()]
negated conditional → KILLED

808

1.1
Location : writeAddressRegister
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:addressFirstWriteClearsTheUnusedFifteenthBitOfT()]
Replaced Shift Left with Shift Right → KILLED

2.2
Location : writeAddressRegister
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:addressFirstWriteClearsTheUnusedFifteenthBitOfT()]
Replaced bitwise OR with AND → KILLED

3.3
Location : writeAddressRegister
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:scrollAndAddressRegistersShareTheSameWriteLatch()]
Replaced bitwise AND with OR → KILLED

4.4
Location : writeAddressRegister
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:addressFirstWriteClearsTheUnusedFifteenthBitOfT()]
Replaced bitwise AND with OR → KILLED

5.5
Location : writeAddressRegister
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:addressFirstWriteClearsTheUnusedFifteenthBitOfT()]
Replaced bitwise AND with OR → KILLED

812

1.1
Location : writeAddressRegister
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:vramAddressReflectsTheLastAddressWritten()]
Replaced bitwise AND with OR → KILLED

2.2
Location : writeAddressRegister
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:vramAddressReflectsTheLastAddressWritten()]
Replaced bitwise OR with AND → KILLED

3.3
Location : writeAddressRegister
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:vramAddressReflectsTheLastAddressWritten()]
Replaced bitwise AND with OR → KILLED

815

1.1
Location : writeAddressRegister
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:scrollAndAddressRegistersShareTheSameWriteLatch()]
negated conditional → KILLED

827

1.1
Location : readDataRegister
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:readBufferQuirkDelaysNonPaletteReadsByOneRead()]
Replaced bitwise AND with OR → KILLED

829

1.1
Location : readDataRegister
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:readMemoryRoutesExactlyThreeFHundredToPaletteNotNametable()]
changed conditional boundary → KILLED

2.2
Location : readDataRegister
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:readBufferQuirkDelaysNonPaletteReadsByOneRead()]
negated conditional → KILLED

834

1.1
Location : readDataRegister
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:paletteReadRefreshesTheBufferFromTheNametableByteUnderneathNotAbove()]
Replaced integer subtraction with addition → KILLED

839

1.1
Location : readDataRegister
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:readDataRegisterAutoIncrementsAfterEachRead()]
Replaced integer addition with subtraction → KILLED

2.2
Location : readDataRegister
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:readBufferQuirkDelaysNonPaletteReadsByOneRead()]
Replaced bitwise AND with OR → KILLED

840

1.1
Location : readDataRegister
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:readBufferQuirkDelaysNonPaletteReadsByOneRead()]
replaced int return with 0 for com/rox/ppu/PPU::readDataRegister → KILLED

844

1.1
Location : writeDataRegister
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:nametableSnapshotReflectsWrittenData()]
Replaced bitwise AND with OR → KILLED

2.2
Location : writeDataRegister
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:nametableSnapshotReflectsWrittenData()]
removed call to com/rox/ppu/PPU::writeMemory → KILLED

845

1.1
Location : writeDataRegister
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:vramIncrementDefaultsToOne()]
Replaced bitwise AND with OR → KILLED

2.2
Location : writeDataRegister
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:vramIncrementDefaultsToOne()]
Replaced integer addition with subtraction → KILLED

850

1.1
Location : readMemory
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:singleScreenLowerMirroringAliasesAllFourLogicalNametablesToTheFirstPhysicalTable()]
changed conditional boundary → KILLED

2.2
Location : readMemory
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:readDataRegisterAutoIncrementsAfterEachRead()]
negated conditional → KILLED

851

1.1
Location : readMemory
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:readDataRegisterAutoIncrementsAfterEachRead()]
replaced int return with 0 for com/rox/ppu/PPU::readMemory → KILLED

853

1.1
Location : readMemory
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:readMemoryRoutesExactlyThreeFHundredToPaletteNotNametable()]
negated conditional → KILLED

2.2
Location : readMemory
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:readMemoryRoutesExactlyThreeFHundredToPaletteNotNametable()]
changed conditional boundary → KILLED

854

1.1
Location : readMemory
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:singleScreenLowerMirroringAliasesAllFourLogicalNametablesToTheFirstPhysicalTable()]
replaced int return with 0 for com/rox/ppu/PPU::readMemory → KILLED

856

1.1
Location : readMemory
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:paletteReadsAreImmediateWithNoBufferDelay()]
replaced int return with 0 for com/rox/ppu/PPU::readMemory → KILLED

860

1.1
Location : writeMemory
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:nametableSnapshotReflectsWrittenData()]
negated conditional → KILLED

2.2
Location : writeMemory
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:nametableSnapshotReflectsWrittenData()]
changed conditional boundary → KILLED

861

1.1
Location : writeMemory
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:readDataRegisterAutoIncrementsAfterEachRead()]
Replaced bitwise AND with OR → KILLED

2.2
Location : writeMemory
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:readDataRegisterAutoIncrementsAfterEachRead()]
removed call to com/rox/cartridge/Cartridge::writeChr → KILLED

862

1.1
Location : writeMemory
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:paletteSnapshotResolvesTheBackdropMirrorQuirkBothWays()]
changed conditional boundary → KILLED

2.2
Location : writeMemory
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:nametableSnapshotReflectsWrittenData()]
negated conditional → KILLED

863

1.1
Location : writeMemory
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:nametableSnapshotReflectsWrittenData()]
Replaced bitwise AND with OR → KILLED

865

1.1
Location : writeMemory
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:paletteSnapshotResolvesTheBackdropMirrorQuirkBothWays()]
Replaced bitwise AND with OR → KILLED

871

1.1
Location : resolveNametableIndex
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:nametableSnapshotReflectsWrittenData()]
Replaced bitwise AND with OR → KILLED

872

1.1
Location : resolveNametableIndex
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:nametableSnapshotReflectsWrittenData()]
Replaced bitwise AND with OR → KILLED

2.2
Location : resolveNametableIndex
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:verticalMirroringDoesNotAliasLeftAndRightNametables()]
Replaced Shift Right with Shift Left → KILLED

873

1.1
Location : resolveNametableIndex
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:nametableSnapshotReflectsWrittenData()]
Replaced bitwise AND with OR → KILLED

875

1.1
Location : resolveNametableIndex
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:singleScreenLowerMirroringAliasesAllFourLogicalNametablesToTheFirstPhysicalTable()]
Replaced integer addition with subtraction → KILLED

2.2
Location : resolveNametableIndex
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:verticalMirroringDoesNotAliasLeftAndRightNametables()]
Replaced integer multiplication with division → KILLED

3.3
Location : resolveNametableIndex
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:verticalMirroringDoesNotAliasLeftAndRightNametables()]
replaced int return with 0 for com/rox/ppu/PPU::resolveNametableIndex → KILLED

879

1.1
Location : resolvePhysicalNametable
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:verticalMirroringDoesNotAliasLeftAndRightNametables()]
replaced int return with 0 for com/rox/ppu/PPU::resolvePhysicalNametable → KILLED

880

1.1
Location : resolvePhysicalNametable
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:readMemoryRoutesExactlyThreeFHundredToPaletteNotNametable()]
Replaced Shift Right with Shift Left → KILLED

881

1.1
Location : resolvePhysicalNametable
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:verticalMirroringDoesNotAliasLeftAndRightNametables()]
Replaced bitwise AND with OR → KILLED

893

1.1
Location : resolvePaletteIndex
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:paletteSnapshotIsTheDocumentedSize()]
Replaced bitwise AND with OR → KILLED

894

1.1
Location : resolvePaletteIndex
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:paletteSnapshotResolvesTheBackdropMirrorQuirkBothWays()]
Replaced bitwise AND with OR → KILLED

2.2
Location : resolvePaletteIndex
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:paletteSnapshotIsTheDocumentedSize()]
negated conditional → KILLED

3.3
Location : resolvePaletteIndex
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:paletteSnapshotResolvesTheBackdropMirrorQuirkBothWays()]
negated conditional → KILLED

4.4
Location : resolvePaletteIndex
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:paletteSnapshotResolvesTheBackdropMirrorQuirkBothWays()]
changed conditional boundary → KILLED

895

1.1
Location : resolvePaletteIndex
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:paletteSnapshotIsTheDocumentedSize()]
negated conditional → KILLED

2.2
Location : resolvePaletteIndex
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:paletteSnapshotResolvesTheBackdropMirrorQuirkBothWays()]
replaced int return with 0 for com/rox/ppu/PPU::resolvePaletteIndex → KILLED

3.3
Location : resolvePaletteIndex
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:paletteSnapshotIsTheDocumentedSize()]
Replaced integer subtraction with addition → KILLED

902

1.1
Location : writeOamDma
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:writeOamDmaCopiesTheWholePageStartingAtTheCurrentOamAddressWrappingModTwoFiftySix()]
removed call to com/rox/ppu/PPU::writeOamData → KILLED

909

1.1
Location : consumeOamDmaStallCycles
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:consumeOamDmaStallCyclesIsOneShotFiringOnlyAfterADma()]
negated conditional → KILLED

911

1.1
Location : consumeOamDmaStallCycles
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:consumeOamDmaStallCyclesIsOneShotFiringOnlyAfterADma()]
replaced int return with 0 for com/rox/ppu/PPU::consumeOamDmaStallCycles → KILLED

917

1.1
Location : controlRegister
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:controlRegisterCapturesRawValue()]
replaced int return with 0 for com/rox/ppu/PPU::controlRegister → KILLED

922

1.1
Location : controlRegisterDecoded
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:controlRegisterDecodedReflectsTheLastWrite()]
replaced return value with null for com/rox/ppu/PPU::controlRegisterDecoded → KILLED

926

1.1
Location : maskRegister
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:maskRegisterIsCapturedButOtherwiseUnused()]
replaced int return with 0 for com/rox/ppu/PPU::maskRegister → KILLED

931

1.1
Location : scrollX
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:scrollRegisterCapturesXThenYInOrder()]
Replaced Shift Left with Shift Right → KILLED

2.2
Location : scrollX
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:scrollRegisterCapturesXThenYInOrder()]
Replaced bitwise OR with AND → KILLED

3.3
Location : scrollX
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:scrollRegisterCapturesXThenYInOrder()]
replaced int return with 0 for com/rox/ppu/PPU::scrollX → KILLED

4.4
Location : scrollX
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:scrollRegisterCapturesXThenYInOrder()]
Replaced bitwise AND with OR → KILLED

936

1.1
Location : scrollY
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:scrollRegisterCapturesXThenYInOrder()]
Replaced Shift Right with Shift Left → KILLED

2.2
Location : scrollY
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:scrollRegisterCapturesXThenYInOrder()]
Replaced bitwise AND with OR → KILLED

3.3
Location : scrollY
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:scrollRegisterCapturesXThenYInOrder()]
Replaced Shift Left with Shift Right → KILLED

4.4
Location : scrollY
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:scrollRegisterCapturesXThenYInOrder()]
Replaced Shift Right with Shift Left → KILLED

5.5
Location : scrollY
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:scrollRegisterCapturesXThenYInOrder()]
Replaced bitwise AND with OR → KILLED

6.6
Location : scrollY
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:scrollRegisterCapturesXThenYInOrder()]
Replaced bitwise OR with AND → KILLED

7.7
Location : scrollY
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:scrollRegisterCapturesXThenYInOrder()]
replaced int return with 0 for com/rox/ppu/PPU::scrollY → KILLED

941

1.1
Location : vramAddress
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:vramAddressReflectsTheLastAddressWritten()]
replaced int return with 0 for com/rox/ppu/PPU::vramAddress → KILLED

949

1.1
Location : temporaryVramAddress
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:addressFirstWriteClearsTheUnusedFifteenthBitOfT()]
replaced int return with 0 for com/rox/ppu/PPU::temporaryVramAddress → KILLED

953

1.1
Location : scanline
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:dotAndScanlineAdvanceTogetherAndWrapAtScanlineEnd()]
replaced int return with 0 for com/rox/ppu/PPU::scanline → KILLED

957

1.1
Location : dot
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:dotAndScanlineAdvanceTogetherAndWrapAtScanlineEnd()]
replaced int return with 0 for com/rox/ppu/PPU::dot → KILLED

966

1.1
Location : vblankFlag
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:vblankFlagReflectsTheFlagWithoutTheReadAndClearSideEffect()]
replaced boolean return with false for com/rox/ppu/PPU::vblankFlag → KILLED

2.2
Location : vblankFlag
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:vblankFlagStartsFalse()]
replaced boolean return with true for com/rox/ppu/PPU::vblankFlag → KILLED

970

1.1
Location : oamAddress
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:oamAddressReflectsTheLastAddressWritten()]
replaced int return with 0 for com/rox/ppu/PPU::oamAddress → KILLED

975

1.1
Location : nametableSnapshot
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:nametableSnapshotIsADefensiveCopy()]
replaced return value with null for com/rox/ppu/PPU::nametableSnapshot → KILLED

980

1.1
Location : oamSnapshot
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:oamSnapshotIsADefensiveCopy()]
replaced return value with null for com/rox/ppu/PPU::oamSnapshot → KILLED

985

1.1
Location : framebuffer
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:framebufferIsADefensiveCopy()]
replaced return value with null for com/rox/ppu/PPU::framebuffer → KILLED

991

1.1
Location : rgbFramebuffer
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:rgbFramebufferConvertsEveryRawIndexThroughNesPalette()]
negated conditional → KILLED

2.2
Location : rgbFramebuffer
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:rgbFramebufferIsTheDocumentedSize()]
changed conditional boundary → KILLED

994

1.1
Location : rgbFramebuffer
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:rgbFramebufferIsTheDocumentedSize()]
replaced return value with null for com/rox/ppu/PPU::rgbFramebuffer → KILLED

1005

1.1
Location : paletteSnapshot
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:paletteSnapshotIsTheDocumentedSize()]
changed conditional boundary → KILLED

2.2
Location : paletteSnapshot
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:paletteSnapshotReflectsDirectlyWrittenEntries()]
negated conditional → KILLED

1006

1.1
Location : paletteSnapshot
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:paletteSnapshotReflectsDirectlyWrittenEntries()]
Replaced integer addition with subtraction → KILLED

1008

1.1
Location : paletteSnapshot
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:paletteSnapshotIsTheDocumentedSize()]
replaced return value with null for com/rox/ppu/PPU::paletteSnapshot → KILLED

1013

1.1
Location : snapshot
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:snapshotArraysAreCopiesNotLiveViews()]
replaced return value with null for com/rox/ppu/PPU::snapshot → KILLED

1030

1.1
Location : checkRestorable
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:restoreRejectsWronglySizedArrays()]
removed call to com/rox/ppu/PPU::requireSameSize → KILLED

1031

1.1
Location : checkRestorable
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[test-template:rejectedRestoreChangesNothingWhicheverArrayIsWrong(java.lang.String)]/[test-template-invocation:#2]
removed call to com/rox/ppu/PPU::requireSameSize → KILLED

1032

1.1
Location : checkRestorable
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[test-template:rejectedRestoreChangesNothingWhicheverArrayIsWrong(java.lang.String)]/[test-template-invocation:#3]
removed call to com/rox/ppu/PPU::requireSameSize → KILLED

1034

1.1
Location : checkRestorable
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[test-template:rejectedRestoreChangesNothingWhicheverArrayIsWrong(java.lang.String)]/[test-template-invocation:#4]
removed call to com/rox/ppu/PPU::requireSameSize → KILLED

1035

1.1
Location : checkRestorable
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[test-template:rejectedRestoreChangesNothingWhicheverArrayIsWrong(java.lang.String)]/[test-template-invocation:#5]
removed call to com/rox/ppu/PPU::requireSameSize → KILLED

1036

1.1
Location : checkRestorable
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[test-template:rejectedRestoreChangesNothingWhicheverArrayIsWrong(java.lang.String)]/[test-template-invocation:#6]
removed call to com/rox/ppu/PPU::requireSameSize → KILLED

1037

1.1
Location : checkRestorable
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[test-template:rejectedRestoreChangesNothingWhicheverArrayIsWrong(java.lang.String)]/[test-template-invocation:#7]
removed call to com/rox/ppu/PPU::requireSameSize → KILLED

1038

1.1
Location : checkRestorable
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[test-template:rejectedRestoreChangesNothingWhicheverArrayIsWrong(java.lang.String)]/[test-template-invocation:#8]
removed call to com/rox/ppu/PPU::requireSameSize → KILLED

1039

1.1
Location : checkRestorable
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:restoreRejectsWronglySizedArrays()]
negated conditional → KILLED

1052

1.1
Location : restore
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:restoreRejectsWronglySizedArrays()]
removed call to com/rox/ppu/PPU::checkRestorable → KILLED

1053

1.1
Location : restore
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:restoredMidScanlineWithSpritesInFlightRunsInLockstep()]
removed call to com/rox/ppu/PPU::copy → KILLED

1054

1.1
Location : restore
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:restoredMidScanlineWithSpritesInFlightRunsInLockstep()]
removed call to com/rox/ppu/PPU::copy → KILLED

1055

1.1
Location : restore
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:restoredMidScanlineWithSpritesInFlightRunsInLockstep()]
removed call to com/rox/ppu/PPU::copy → KILLED

1087

1.1
Location : restore
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:restoredMidScanlineWithSpritesInFlightRunsInLockstep()]
removed call to com/rox/ppu/PPU::copy → KILLED

1092

1.1
Location : restore
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:restoredMidScanlineWithSpritesInFlightRunsInLockstep()]
removed call to com/rox/ppu/PPU::copy → KILLED

1093

1.1
Location : restore
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:restoredMidScanlineWithSpritesInFlightRunsInLockstep()]
removed call to com/rox/ppu/PPU::copy → KILLED

1094

1.1
Location : restore
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:restoredMidScanlineWithSpritesInFlightRunsInLockstep()]
removed call to com/rox/ppu/PPU::copy → KILLED

1095

1.1
Location : restore
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:restoredMidScanlineWithSpritesInFlightRunsInLockstep()]
removed call to com/rox/ppu/PPU::copy → KILLED

1096

1.1
Location : restore
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:restoredMidScanlineWithSpritesInFlightRunsInLockstep()]
removed call to java/lang/System::arraycopy → KILLED

1101

1.1
Location : requireSameSize
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:restoredMidScanlineWithSpritesInFlightRunsInLockstep()]
negated conditional → KILLED

1107

1.1
Location : copy
Killed by : com.rox.ppu.PPUTest.[engine:junit-jupiter]/[class:com.rox.ppu.PPUTest]/[method:restoredMidScanlineWithSpritesInFlightRunsInLockstep()]
removed call to java/lang/System::arraycopy → KILLED

Active mutators

Tests examined


Report generated by PIT 1.22.1