diff --git a/game-fork/patches/decompiler-fixes.txt b/game-fork/patches/decompiler-fixes.txt index 11cf703..cf763e1 100644 --- a/game-fork/patches/decompiler-fixes.txt +++ b/game-fork/patches/decompiler-fixes.txt @@ -1090,3 +1090,5 @@ boolean flag = this.onGround || d1 != d1 && d1 < 0.0D; boolean flag = this.onGround || d8 != d1 && d8 < 0.0D; + + diff --git a/game-fork/src-overlay/net/rustnotmc/client/RsxBootstrap.java b/game-fork/src-overlay/net/rustnotmc/client/RsxBootstrap.java index b23a347..5fcb85c 100644 --- a/game-fork/src-overlay/net/rustnotmc/client/RsxBootstrap.java +++ b/game-fork/src-overlay/net/rustnotmc/client/RsxBootstrap.java @@ -140,10 +140,10 @@ public final class RsxBootstrap { * matrices already unwound, so the overlay sets up its own projection and * leaves the state it did not set alone. */ - public static void renderFrame(Minecraft minecraft) { - if (loader == null || surface == null || !surface.available()) { - return; - } +public static void renderFrame(Minecraft minecraft) { + if (loader == null || surface == null || !surface.available()) { + return; + } if (frameFailed) { return; } diff --git a/rsx-client/tools/javap_diff.py b/rsx-client/tools/javap_diff.py new file mode 100644 index 0000000..980f63a --- /dev/null +++ b/rsx-client/tools/javap_diff.py @@ -0,0 +1,86 @@ +#!/usr/bin/env python3 +"""Compare recompiled class files against the reference, instruction by instruction. + +A naive text diff of two javap dumps is useless here: recompiling renumbers the +constant pool, so nearly every line differs by its ``#123`` reference even when +the code is identical. Normalising those references away turns the diff into +something that only reports real behavioural differences. + +Usage: + javap_diff.py [class ...] +""" + +import re +import subprocess +import sys + +# "12: invokevirtual #123 // Method foo" -> "invokevirtual // Method foo" +POOL = re.compile(r"#\d+(?:,\s*\d+)*\b") +# jump targets are printed as "42" / "123" after a branch opcode +OFFSET = re.compile(r"^(\s*\d+:\s*\w+)\s+\d+\s*$") +# ldc_w is only a wider index form of ldc; javap picks whichever fits +LDC_W = re.compile(r"\bldc_w\b") +# instruction offsets shift by one byte per ldc_w/ldc difference, so they carry +# no meaning here; the line order already encodes control flow +OFF = re.compile(r"^\s*\d+:\s*") + + +def dump(javap, classpath, name): + out = subprocess.run( + [javap, "-p", "-c", "-cp", classpath, name], + capture_output=True, text=True, errors="replace") + return out.stdout + + +def normalise(text): + lines = [] + for raw in text.splitlines(): + line = raw.rstrip() + if not line.strip(): + continue + if line.startswith("Compiled from"): + continue + if "major version" in line: + continue + line = POOL.sub("#", line) + line = re.sub(r"#\s+", "# ", line) + line = LDC_W.sub("ldc", line) + m = OFFSET.match(line) + if m: + line = m.group(1) + " " + line = OFF.sub("", line) + lines.append(line.strip()) + return lines + + +def main(argv): + if len(argv) < 4: + sys.exit(__doc__) + javap, ref, new, classes = argv[0], argv[1], argv[2], argv[3:] + + bad = 0 + for cls in classes: + a = normalise(dump(javap, ref, cls)) + b = normalise(dump(javap, new, cls)) + if not a or not b: + print("=== {} : javap produced nothing (ref={} new={})".format( + cls, len(a), len(b))) + bad += 1 + continue + if a == b: + print("=== {} : IDENTICAL ({})".format(cls, len(a))) + continue + sa, sb = set(a), set(b) + only_ref = [x for x in a if x not in sb] + only_new = [x for x in b if x not in sa] + print("=== {} : {} ref / {} new -> {} ref-only, {} new-only".format( + cls, len(a), len(b), len(only_ref), len(only_new))) + bad += 1 + import difflib + for line in list(difflib.unified_diff(a, b, "reference", "rebuilt", lineterm="", n=2))[:80]: + print(" " + line) + return 1 if bad else 0 + + +if __name__ == "__main__": + raise SystemExit(main(sys.argv[1:])) \ No newline at end of file diff --git a/rsx-client/tools/ogg_duration.py b/rsx-client/tools/ogg_duration.py new file mode 100644 index 0000000..4bb37f1 --- /dev/null +++ b/rsx-client/tools/ogg_duration.py @@ -0,0 +1,69 @@ +#!/usr/bin/env python3 +"""Report the real playback duration of Ogg Vorbis files, without decoding audio. + +Reads the sample rate out of the Vorbis identification header and the total +sample count from the granule position of the final OggS page, then divides. + +This is how you tell a sound file that is genuinely shorter from a sound that +merely stops early: the file either contains fewer samples or it does not. + +Usage: + ogg_duration.py [file.ogg ...] +""" + +import struct +import sys + + +def info(path): + with open(path, "rb") as fh: + data = fh.read() + + mark = data.find(b"\x01vorbis") + if mark < 0: + return None + # packet type(1) + 'vorbis'(6) + version(4) + channels(1) -> rate(4) + if len(data) < mark + 16: + return None + rate = struct.unpack_from("7.3f}s {:>6} Hz {:>2}ch {:>8} samples {:>6} B".format( + path[-52:], got["seconds"], got["rate"], got["channels"], + got["samples"], got["bytes"])) + return 0 + + +if __name__ == "__main__": + raise SystemExit(main(sys.argv[1:])) \ No newline at end of file