Found the routines in the disassembly DB rather than guessing from data: sub_82447DF0 IDXD tag hash (lbz+extsb, modulus 0x00FFFFDF, magic 0x2101) sub_82447E70 IXUD tag hash (lhz, 64-bit, modulus 0xFFFFFF67 then 0x00FFFFDF) Both transcribed instruction-for-instruction into Python and Rust. IXUD SOLVED. It defeated every single-modulus search because it chains TWO exact moduli -- the loop reduces mod 2^32-153 in 64-bit arithmetic and only the result is folded mod 2^24-33. A polynomial mod M1 folded through M2 is not a polynomial mod anything, which is exactly why the gcd test returned 1. Verified independently: 86/86 record keys and 108,261/108,261 field tags in GP_MAIN_GAME_E.pak, and NoRecord -> 0x1c6d9c96. CORRECTION 1: tag_hash must SIGN-EXTEND each byte (extsb). My reconstruction used unsigned bytes and matched all 1.27M disc names -- every one is ASCII -- while disagreeing on ~90% of random inputs with a byte >= 0x80 (verified: 18096/20000). The disc could never have caught this; only the disassembly did. CORRECTION 2: name_hash's reduction is EXACT, not lossy. The module doc claimed the missing conditional subtract made it something other than %. rlwinm r6,r6, 9,23,31 is just hi>>23, and with RECIP = floor(2^55/M)+1 that is Granlund- Montgomery magic division -- 0 wrong at every quotient boundary across the full 32-bit domain. Retracted. cargo test -p sylpheed-formats --lib hash: 10/10.
49 lines
1.7 KiB
Python
Executable File
49 lines
1.7 KiB
Python
Executable File
#!/usr/bin/env python3
|
|
"""Is a modal YES/NO dialog on screen?
|
|
|
|
Written because `wait_screen.sh --tap A` BLIND-taps A, and on this game's
|
|
"Load game?" dialog the cursor starts on **NO** — so a blind tap answers NO,
|
|
drops back to the save list, and the next tap reopens the dialog. That is a
|
|
stable oscillation, and it burned three consecutive 300 s boots as
|
|
"NO readyroom" while d-pad and A both worked perfectly.
|
|
|
|
The game dims the whole frame behind a modal, so the dialog is detectable
|
|
without knowing which dialog it is: sample the band where the modal sits and
|
|
compare its brightness against the undimmed screen.
|
|
|
|
Measured on the LOAD GAME save list (1279x675):
|
|
|
|
save list, no dialog mean 59.0 / 62.4 p95 164 / 199
|
|
"Load game?" dialog up mean 34.4 p95 113
|
|
|
|
so the threshold sits at 45. Used ONLY to decide whether tapping A is safe:
|
|
with a dialog up, A is the affirmative/OK button; without one, A may mean
|
|
something destructive like "open the dialog again".
|
|
|
|
⚠️ Calibrated on 1 positive and 2 negatives — thin. Widen it as runs collect
|
|
more frames.
|
|
|
|
Usage: dialog_up.py <png> -> prints metrics, exit 0 if a dialog is up
|
|
"""
|
|
import sys
|
|
|
|
import numpy as np
|
|
from PIL import Image
|
|
|
|
THRESHOLD = 45.0
|
|
|
|
|
|
def metric(path):
|
|
im = np.asarray(Image.open(path).convert("L"), dtype=float)
|
|
h, w = im.shape
|
|
box = im[int(h * 0.33):int(h * 0.48), int(w * 0.28):int(w * 0.72)]
|
|
return float(box.mean()), float(np.percentile(box, 95))
|
|
|
|
|
|
if __name__ == "__main__":
|
|
mean, p95 = metric(sys.argv[1])
|
|
up = mean < THRESHOLD
|
|
print("%s mean=%.1f p95=%.1f threshold=%.0f" %
|
|
("dialog" if up else "no-dialog", mean, p95, THRESHOLD))
|
|
sys.exit(0 if up else 1)
|