| 1 | package com.rox.ppu.debug; | |
| 2 | ||
| 3 | /** | |
| 4 | * Computes the 1-4 rectangle segments a fixed-size viewport box splits into when its origin plus size | |
| 5 | * overflows a periodic canvas. The NES nametable grid wraps at its edges - scrolling past the | |
| 6 | * right/bottom seam continues seamlessly back at x=0/y=0 - so a viewport straddling that seam is | |
| 7 | * genuinely two (or, at a corner, four) separate on-screen regions, not one contiguous rectangle. | |
| 8 | * | |
| 9 | * Assumes {@code boxWidth <= canvasWidth} and {@code boxHeight <= canvasHeight} (true for a 256x240 | |
| 10 | * viewport over a 256/512-wide, 240/480-tall nametable grid), so each axis wraps at most once. | |
| 11 | */ | |
| 12 | final class ScrollViewport { | |
| 13 | private ScrollViewport(){ | |
| 14 | } | |
| 15 | ||
| 16 | /** | |
| 17 | * @return between 1 and 4 {@code [x, y, width, height]} rectangles, in canvas coordinates, whose | |
| 18 | * union is the box wrapped onto a {@code canvasWidth x canvasHeight} periodic canvas. | |
| 19 | */ | |
| 20 | static int[][] segments(final int originX, final int originY, final int boxWidth, final int boxHeight, | |
| 21 | final int canvasWidth, final int canvasHeight){ | |
| 22 | final int[][] xSpans = axisSpans(Math.floorMod(originX, canvasWidth), boxWidth, canvasWidth); | |
| 23 | final int[][] ySpans = axisSpans(Math.floorMod(originY, canvasHeight), boxHeight, canvasHeight); | |
| 24 | ||
| 25 |
1
1. segments : Replaced integer multiplication with division → KILLED |
final int[][] segments = new int[xSpans.length * ySpans.length][4]; |
| 26 | int i = 0; | |
| 27 | for (final int[] xSpan : xSpans){ | |
| 28 | for (final int[] ySpan : ySpans){ | |
| 29 |
1
1. segments : Changed increment from 1 to -1 → KILLED |
segments[i++] = new int[]{xSpan[0], ySpan[0], xSpan[1], ySpan[1]}; |
| 30 | } | |
| 31 | } | |
| 32 |
1
1. segments : replaced return value with null for com/rox/ppu/debug/ScrollViewport::segments → KILLED |
return segments; |
| 33 | } | |
| 34 | ||
| 35 | /** @return {@code [[start, length]]}, or {@code [[start, firstLength], [0, remainder]]} if it wraps. */ | |
| 36 | private static int[][] axisSpans(final int start, final int length, final int canvasLength){ | |
| 37 |
1
1. axisSpans : Replaced integer subtraction with addition → KILLED |
final int firstLength = Math.min(length, canvasLength - start); |
| 38 |
2
1. axisSpans : changed conditional boundary → KILLED 2. axisSpans : negated conditional → KILLED |
if (firstLength >= length){ |
| 39 |
1
1. axisSpans : replaced return value with null for com/rox/ppu/debug/ScrollViewport::axisSpans → KILLED |
return new int[][]{{start, length}}; |
| 40 | } | |
| 41 |
2
1. axisSpans : Replaced integer subtraction with addition → KILLED 2. axisSpans : replaced return value with null for com/rox/ppu/debug/ScrollViewport::axisSpans → KILLED |
return new int[][]{{start, firstLength}, {0, length - firstLength}}; |
| 42 | } | |
| 43 | } | |
Mutations | ||
| 25 |
1.1 |
|
| 29 |
1.1 |
|
| 32 |
1.1 |
|
| 37 |
1.1 |
|
| 38 |
1.1 2.2 |
|
| 39 |
1.1 |
|
| 41 |
1.1 2.2 |