From b3c2adc51f1c4af2a93269f5a6c2eadc5b1951fa Mon Sep 17 00:00:00 2001 From: downthecrop Date: Fri, 25 Oct 2024 15:54:39 -0700 Subject: [PATCH] support scaled fixed HD --- client/src/main/java/rt4/DisplayMode.java | 6 ++ client/src/main/java/rt4/GameShell.java | 1 + client/src/main/java/rt4/GlRenderer.java | 15 +++- .../src/main/kotlin/KondoKit/plugin.kt | 87 +++++++++++++++---- 4 files changed, 88 insertions(+), 21 deletions(-) diff --git a/client/src/main/java/rt4/DisplayMode.java b/client/src/main/java/rt4/DisplayMode.java index 440e79d..58bf779 100644 --- a/client/src/main/java/rt4/DisplayMode.java +++ b/client/src/main/java/rt4/DisplayMode.java @@ -79,6 +79,12 @@ public final class DisplayMode { @OriginalMember(owner = "client!pm", name = "a", descriptor = "(ZIZIZII)V") public static void setWindowMode(@OriginalArg(0) boolean replaceCanvas, @OriginalArg(1) int newMode, @OriginalArg(2) boolean useHD, @OriginalArg(3) int currentMode, @OriginalArg(5) int width, @OriginalArg(6) int height) { + if(!GameShell.canvas.isShowing()){ + GameShell.frame.add(GameShell.canvas); + GameShell.canvas.revalidate(); + GameShell.frame.revalidate(); + GameShell.canvas.repaint(); + } if (useHD) { GlRenderer.quit(); } diff --git a/client/src/main/java/rt4/GameShell.java b/client/src/main/java/rt4/GameShell.java index 80a799d..9bd0bd6 100644 --- a/client/src/main/java/rt4/GameShell.java +++ b/client/src/main/java/rt4/GameShell.java @@ -323,6 +323,7 @@ public abstract class GameShell extends Applet implements Runnable, FocusListene @OriginalMember(owner = "client!rc", name = "b", descriptor = "(B)V") public final synchronized void addCanvas() { if (canvas != null) { + // Remove the old canvas if it exists canvas.removeFocusListener(this); canvas.getParent().remove(canvas); } diff --git a/client/src/main/java/rt4/GlRenderer.java b/client/src/main/java/rt4/GlRenderer.java index b42e0de..c7a7d2a 100644 --- a/client/src/main/java/rt4/GlRenderer.java +++ b/client/src/main/java/rt4/GlRenderer.java @@ -24,6 +24,8 @@ public final class GlRenderer { public static float hFOV = 0; + public static int[] pixelData = null; + @OriginalMember(owner = "client!tf", name = "c", descriptor = "F") private static float aFloat30; @@ -67,7 +69,7 @@ public final class GlRenderer { private static int maxTextureCoords; @OriginalMember(owner = "client!tf", name = "E", descriptor = "Lgl!javax/media/opengl/GLDrawable;") - private static GLDrawable drawable; + public static GLDrawable drawable; @OriginalMember(owner = "client!tf", name = "H", descriptor = "Z") public static boolean arbVertexProgramSupported; @@ -199,11 +201,20 @@ public final class GlRenderer { @OriginalMember(owner = "client!tf", name = "d", descriptor = "()V") public static void swapBuffers() { try { + pixelData = readPixels(); drawable.swapBuffers(); - } catch (@Pc(3) Exception local3) { + } catch (@Pc(3) Exception local3) {*, } } + @OriginalMember(owner = "client!tf", name = "readPixels", descriptor = "()int[]") + public static int[] readPixels() { + int[] pixels = new int[canvasWidth * canvasHeight]; + IntBuffer buffer = IntBuffer.wrap(pixels); + gl.glReadPixels(0, 0, canvasWidth, canvasHeight, GL2.GL_BGRA, GlRenderer.bigEndian ? GL2.GL_UNSIGNED_INT_8_8_8_8_REV : GL2.GL_UNSIGNED_BYTE, buffer); + return pixels; + } + @OriginalMember(owner = "client!tf", name = "a", descriptor = "(Z)V") public static void setFogEnabled(@OriginalArg(0) boolean enabled) { if (enabled == fogEnabled) { diff --git a/plugin-playground/src/main/kotlin/KondoKit/plugin.kt b/plugin-playground/src/main/kotlin/KondoKit/plugin.kt index 6e1adbb..983576d 100644 --- a/plugin-playground/src/main/kotlin/KondoKit/plugin.kt +++ b/plugin-playground/src/main/kotlin/KondoKit/plugin.kt @@ -34,17 +34,18 @@ import plugin.Plugin import plugin.api.* import plugin.api.API.* import plugin.api.FontColor.fromColor -import rt4.GameShell +import rt4.* import rt4.GameShell.canvas import rt4.GameShell.frame -import rt4.GlRenderer -import rt4.InterfaceList -import rt4.Player -import rt4.SoftwareRaster -import rt4.client.* +import rt4.client.js5Archive8 +import rt4.client.mainLoadState import java.awt.* +import java.awt.Font import java.awt.event.* +import java.awt.image.BufferedImage import java.awt.image.VolatileImage +import java.util.* +import java.util.Timer import javax.swing.* @@ -148,7 +149,7 @@ class plugin : Plugin() { } lastLogin = Player.usernameInput.toString() } - class AltCanvas(private val mainCanvas: Canvas) : JPanel() { + class AltCanvas() : JPanel() { private var gameImage: VolatileImage? = null private var scaleX = 1.0 private var scaleY = 1.0 @@ -186,19 +187,19 @@ class plugin : Plugin() { // Register a KeyAdapter for handling key events addKeyListener(object : KeyAdapter() { override fun keyPressed(e: KeyEvent) { - for (listener in mainCanvas.keyListeners) { + for (listener in canvas.keyListeners) { listener.keyPressed(e) } } override fun keyReleased(e: KeyEvent) { - for (listener in mainCanvas.keyListeners) { + for (listener in canvas.keyListeners) { listener.keyReleased(e) } } override fun keyTyped(e: KeyEvent) { - for (listener in mainCanvas.keyListeners) { + for (listener in canvas.keyListeners) { listener.keyTyped(e) } } @@ -287,27 +288,62 @@ class plugin : Plugin() { val originalY = adjustedY.toInt().coerceIn(0, gameImage!!.height - 1) val newEvent = MouseEvent( - mainCanvas, e.id, e.`when`, e.modifiersEx, + canvas, e.id, e.`when`, e.modifiersEx, originalX, originalY, e.clickCount, e.isPopupTrigger, e.button ) - mainCanvas.dispatchEvent(newEvent) + canvas.dispatchEvent(newEvent) } fun updateGameImage() { validateGameImage() + if (IsHD()) { + renderGlRaster() + } else { + renderSoftwareRaster() + } + repaint() + } + private fun renderGlRaster() { + val pixels = GlRenderer.pixelData // Assuming this holds the int[] BGRA pixel data from GlRenderer.readPixels() + val width = gameImage!!.width + val height = gameImage!!.height + + // Create a BufferedImage with the same dimensions as the gameImage + val bufferedImage = BufferedImage(width, height, BufferedImage.TYPE_INT_BGR) + + // Flip the image vertically by reversing the rows + val flippedPixels = IntArray(width * height) + for (y in 0 until height) { + // Calculate the source row (bottom to top) + val srcY = height - 1 - y + System.arraycopy(pixels, srcY * width, flippedPixels, y * width, width) + } + + // Set the flipped pixel data into the BufferedImage + bufferedImage.setRGB(0, 0, width, height, flippedPixels, 0, width) + + // Draw the BufferedImage onto the VolatileImage + val g = gameImage!!.createGraphics() + try { + g.drawImage(bufferedImage, 0, 0, null) + } finally { + g.dispose() + } + } + + private fun renderSoftwareRaster() { val g = gameImage!!.createGraphics() try { SoftwareRaster.frameBuffer.draw(g) } finally { g.dispose() } - repaint() } } - fun createAltCanvas(mainCanvas: Canvas): AltCanvas { - return AltCanvas(mainCanvas).apply { + fun createAltCanvas(): AltCanvas { + return AltCanvas().apply { preferredSize = Dimension(FIXED_WIDTH, 503) } } @@ -323,14 +359,12 @@ class plugin : Plugin() { val frame: Frame? = GameShell.frame if (frame != null) { // Create the AltCanvas and add it to the main frame - altCanvas = createAltCanvas(canvas) - canvas.isVisible = false + altCanvas = createAltCanvas() // Use BorderLayout for better layout control frame.layout = BorderLayout() // Add the AltCanvas in the center to ensure it scales properly with the window size altCanvas?.let { frame.add(it, BorderLayout.NORTH) } - frame.remove(canvas) } } @@ -415,6 +449,20 @@ class plugin : Plugin() { frame.layout = BorderLayout() frame.add(rightPanelWrapper, BorderLayout.EAST) + // Create a timer to delay execution by 2 seconds + Timer().schedule(object : TimerTask() { + override fun run() { + println("mode is: " + GetWindowMode().toString()) + if (GetWindowMode() != WindowMode.FIXED) { + // Perform any actions needed for non-fixed mode + } else { + //if (canvas.isShowing) { + // frame.remove(canvas) + // } + } + } + }, 2000) // 2000 milliseconds = 2 seconds + frame.revalidate() frame.repaint() pluginsReloaded = true @@ -490,7 +538,8 @@ class plugin : Plugin() { } override fun LateDraw(timeDelta: Long){ - // Update game image here + // Clear original canvas for scaled + if(!initialized) return altCanvas?.updateGameImage() }