Skip to content

Commit

Permalink
PlatformGraphics: More enhancements to drawing routines.
Browse files Browse the repository at this point in the history
flushGraphics wasn't accessing indices correctly in cases where
the image to be rendered didn't cover the whole canvas (games that
do partial screen repaints tend to use this a lot), and
draw/getPixels didn't have very robust validation steps.

Probably fixes all the remaining Karma Studios games. See #50.
  • Loading branch information
AShiningRay committed Feb 23, 2025
1 parent 2c6d38e commit 9995577
Showing 1 changed file with 35 additions and 13 deletions.
48 changes: 35 additions & 13 deletions src/org/recompile/mobile/PlatformGraphics.java
Original file line number Diff line number Diff line change
Expand Up @@ -232,8 +232,7 @@ public void flushGraphics(Image image, int x, int y, int width, int height)

try
{
BufferedImage sub = image.platformImage.getCanvas().getSubimage(x, y, width, height);
final int[] pixels = ((DataBufferInt) sub.getRaster().getDataBuffer()).getData();
final int[] pixels = ((DataBufferInt) image.platformImage.getCanvas().getRaster().getDataBuffer()).getData();
int[] overlayData = null;

// This one is rather costly, as it has to draw overlays on the corners of the screen with gaussian filtering applied.
Expand All @@ -244,16 +243,16 @@ public void flushGraphics(Image image, int x, int y, int width, int height)
}

// Render the resulting image
for (int j = 0; j < height; j++)
for (int j = y; j < height+y; j++)
{
for (int i = 0; i < width; i++)
for (int i = x; i < width+x; i++)
{
int destIndex = j * canvas.getWidth() + i;
int srcIndex = j * width + i;
int srcIndex = j * image.getWidth() + i;

// The image data CAN go out of the destination bounds, we just can't draw it whenever it does.
if (x + i < 0 || x + i >= canvas.getWidth()) { continue; }
if (y + j < 0 || y + j >= canvas.getHeight()) { continue; }
if (i < 0 || i >= canvas.getWidth()) { continue; }
if (j < 0 || j >= canvas.getHeight()) { continue; }
if (destIndex < 0 || destIndex >= canvasData.length) { continue; }
if (srcIndex < 0 || srcIndex >= pixels.length) { continue; }

Expand Down Expand Up @@ -698,20 +697,29 @@ public void drawPixels(short[] pixels, boolean transparency, int offset, int sca
if (pixels == null) { throw new NullPointerException("drawPixels(short) received a null pixel array"); }
if (offset < 0 || offset >= pixels.length) { throw new ArrayIndexOutOfBoundsException("drawPixels(short) index out of bounds:" + width + " * " + height + "| len:" + pixels.length); }

if (scanlength > 0)
{
if (offset + scanlength * (height - 1) + width > pixels.length) { throw new ArrayIndexOutOfBoundsException(); }
}
else
{
if (offset + width > pixels.length || offset + scanlength * (height - 1) < 0) { throw new ArrayIndexOutOfBoundsException(); }
}

BufferedImage temp = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
int[] data = ((DataBufferInt) temp.getRaster().getDataBuffer()).getData();

// Prepare the pixel data
for (int row = 0; row < height; row++)
{
int srcIndex = offset + row * scanlength;
for (int col = 0; col < width; col++)
{
int index = offset + (col) + (row * scanlength);
data[row * width + col] = pixelToColor(pixels[index], format);
data[row * width + col] = pixelToColor(pixels[srcIndex + col], format);
if (!transparency) { data[row * width + col] = (data[row * width + col] & 0x00FFFFFF) | 0xFF000000; } // Set alpha to 255
}
}

gc.drawImage(manipulateImage(temp, manipulation), x, y, null);
}

Expand Down Expand Up @@ -824,17 +832,31 @@ public void getPixels(byte[] pixels, byte[] transparencyMask, int offset, int sc

public void getPixels(int[] pixels, int offset, int scanlength, int x, int y, int width, int height, int format)
{
if (width <= 0 || height <= 0) { return; } // We have no pixels to copy
if (pixels == null) { throw new NullPointerException("int array cannot be null"); }
if (x < 0 || y < 0 || x + width > canvas.getWidth() || y + height > canvas.getHeight())
{
throw new IllegalArgumentException("Requested copy area exceeds bounds of the image");
}

canvas.getRGB(x, y, width, height, pixels, offset, scanlength);
}

public void getPixels(short[] pixels, int offset, int scanlength, int x, int y, int width, int height, int format)
{
if (width <= 0 || height <= 0) { return; } // We have no pixels to copy
if (pixels == null) { throw new NullPointerException("short array cannot be null"); }
if (x < 0 || y < 0 || x + width > canvas.getWidth() || y + height > canvas.getHeight())
{
throw new IllegalArgumentException("Requested copy area exceeds bounds of the image");
}

for(int row=0; row<height; row++)
{
for (int col=0; col<width; col++)
{
int pixelIndex = offset + (col) + (row * scanlength);
pixels[pixelIndex] = colorToShortPixel(canvas.getRGB(col+x, row+y), format);
int pixelIndex = offset + col + (row * scanlength);
pixels[pixelIndex] = colorToShortPixel(canvasData[col+x + (row+y)*canvas.getWidth()], format);
}
}
}
Expand Down

0 comments on commit 9995577

Please sign in to comment.