HUD: размер экрана из контекста и rsxm-hud

This commit is contained in:
SashegDev
2026-10-17 03:45:59 +03:00
parent b5ffe0e9d7
commit 108c001af6
6 changed files with 80 additions and 11 deletions
@@ -385,6 +385,16 @@ public final class Rsx {
return h.scale();
}
/** Screen width in pixels, 0 when the game did not say. */
public int width() {
return h == null ? 0 : h.width();
}
/** Screen height in pixels, 0 when the game did not say. */
public int height() {
return h == null ? 0 : h.height();
}
/** A solid rectangle; alpha 0..1. */
public void rect(float x, float y, float w, float height, int rgb,
float alpha) {
+4 -8
View File
@@ -41,18 +41,14 @@ public final class Hud {
return Ui.scale();
}
/**
* Screen size in HUD units, or 0 when it cannot be read.
*
* The context does not expose it by name, so this stays 0 until a build
* gives us a way; callers fall back to the game's own scale factor.
*/
/** Screen width, 0 when the game did not say. */
public int width() {
return 0;
return HudHook.width();
}
/** Screen height, 0 when the game did not say. */
public int height() {
return 0;
return HudHook.height();
}
/** A solid rectangle. Colour is 0xRRGGBB, alpha 0..1. */
+46
View File
@@ -142,6 +142,52 @@ public final class HudHook {
}
}
/**
* Screen size, read off the context.
*
* The context offers two no-argument int getters and nothing names them, so
* they are told apart by what they can only be: on any window the larger one
* is the width. Getting this wrong only mirrors the panel, it cannot break
* the frame.
*/
static int width() {
int[] s = size();
return s == null ? 0 : Math.max(s[0], s[1]);
}
static int height() {
int[] s = size();
return s == null ? 0 : Math.min(s[0], s[1]);
}
private static int[] size;
private static synchronized int[] size() {
if (size != null || context == null) {
return size;
}
java.util.List<Integer> found = new ArrayList<Integer>();
for (Class<?> c = context.getClass(); c != null; c = c.getSuperclass()) {
for (Method m : c.getDeclaredMethods()) {
if (m.getParameterTypes().length != 0
|| m.getReturnType() != int.class) {
continue;
}
try {
m.setAccessible(true);
found.add(Integer.valueOf(((Integer) m.invoke(context))
.intValue()));
} catch (Throwable ignored) {
}
}
}
if (found.size() >= 2) {
size = new int[] {found.get(0).intValue(), found.get(1).intValue()};
Log.info("HUD: screen " + width() + "x" + height());
}
return size;
}
/** True while a mod callback is running, i.e. Rsx.hud() is meaningful. */
public static boolean inside() {
return context != null;
+12 -3
View File
@@ -1,11 +1,20 @@
// Test stand-in for the game's HUD render context.
//
// One method takes a draw command. The bridge finds it by shape rather than by
// name, which is what makes the binding survive the next re-obfuscation.
// One method takes a draw command, and two no-argument int getters give the
// screen size. The bridge finds the submit method by shape and tells the two
// getters apart by which is larger, so the names here do not matter.
public class fakectx {
public int screenWidth() {
return 1920;
}
public int screenHeight() {
return 1080;
}
public void accept(fakecmd command) {
fakebatch.submit(command);
}
}
}
+7
View File
@@ -18,6 +18,8 @@ public class HudMod implements RsxMod {
public static int glyphs;
private final Runnable draw = new Runnable() {
private int reported;
@Override
public void run() {
frames++;
@@ -25,6 +27,11 @@ public class HudMod implements RsxMod {
if (hud == null || !hud.available()) {
return;
}
if (reported == 0 && hud.width() > 0) {
reported = 1;
Rsx.info("HudMod screen: " + hud.width() + "x" + hud.height()
+ " scale=" + hud.scale());
}
hud.rect(8, 8, 40, 12, 0x20201C, 0.85f);
rects++;
hud.text(8, 8, "42 ms", 0xECE3DB, 1f);
+1
View File
@@ -288,6 +288,7 @@ def main():
("panel drew a rectangle and a label",
"color=20201c" in out and "textures/font/ascii.png" in out
and "color=ece3db" in out),
("screen size read from the context", "HudMod screen: 1920x1080" in out),
("panel stops when the game hides the HUD",
"HUD hidden (what F3 does)" in out
and "frame 0 commands=0" in out and "frame 2 commands=0" in out),