Research
This commit is contained in:
parent
28cbbe3470
commit
a9153546ae
56 changed files with 6731 additions and 258 deletions
107
tools/hud_icon_match.py
Normal file
107
tools/hud_icon_match.py
Normal file
|
|
@ -0,0 +1,107 @@
|
|||
IN_BIN = r"K:\ghidra\Crusader_Decomp\binary\Crusader - No Remorse Memdump Weapons.bin"
|
||||
W,H = 1024,512
|
||||
# regions
|
||||
HUD_BOX = (80,44,360,92) # left,top,right,bot
|
||||
VSTRIP_X0, VSTRIP_X1 = 956, 1023
|
||||
import os, sys
|
||||
with open(IN_BIN,'rb') as f:
|
||||
data = f.read()
|
||||
count = min(len(data)//2, W*H)
|
||||
# build RGB rows
|
||||
rows = []
|
||||
for y in range(H):
|
||||
row = []
|
||||
for x in range(W):
|
||||
i = y*W + x
|
||||
if i < count:
|
||||
off = i*2
|
||||
val = data[off] | (data[off+1]<<8)
|
||||
b = (val & 0x1F) << 3
|
||||
g = ((val >>5) & 0x1F) << 3
|
||||
r = ((val >>10) & 0x1F) << 3
|
||||
else:
|
||||
r=g=b=0
|
||||
row.append((r,g,b))
|
||||
rows.append(row)
|
||||
# extract HUD crop
|
||||
lx,ty,rx,by = HUD_BOX
|
||||
w = rx-lx; h = by-ty
|
||||
hud = [[rows[y][x] for x in range(lx,rx)] for y in range(ty,by)]
|
||||
# build mask for HUD
|
||||
hud_mask = [[(1 if any(ch!=0 for ch in hud[y][x]) else 0) for x in range(w)] for y in range(h)]
|
||||
# extract vstrip area and find blobs
|
||||
vx0,vx1 = VSTRIP_X0, VSTRIP_X1
|
||||
vw = vx1-vx0+1
|
||||
vrows = [[rows[y][x] for x in range(vx0,vx1+1)] for y in range(H)]
|
||||
# mask and flood-fill
|
||||
mask = [[1 if any(ch!=0 for ch in vrows[y][x]) else 0 for x in range(vw)] for y in range(H)]
|
||||
visited = [[0]*vw for _ in range(H)]
|
||||
from collections import deque
|
||||
blobs = []
|
||||
for y in range(H):
|
||||
for x in range(vw):
|
||||
if mask[y][x] and not visited[y][x]:
|
||||
q=deque([(x,y)])
|
||||
visited[y][x]=1
|
||||
xs=[]; ys=[]
|
||||
while q:
|
||||
cx,cy=q.popleft()
|
||||
xs.append(cx); ys.append(cy)
|
||||
for dx,dy in ((1,0),(-1,0),(0,1),(0,-1)):
|
||||
nx,ny = cx+dx, cy+dy
|
||||
if 0<=nx<vw and 0<=ny<H and mask[ny][nx] and not visited[ny][nx]:
|
||||
visited[ny][nx]=1; q.append((nx,ny))
|
||||
x0,x1 = min(xs), max(xs)
|
||||
y0,y1 = min(ys), max(ys)
|
||||
area = len(xs)
|
||||
blobs.append((x0,y0,x1,y1,area))
|
||||
# sort blobs by y (top to bottom)
|
||||
blobs.sort(key=lambda b: b[1])
|
||||
print('Found', len(blobs), 'blobs in vstrip')
|
||||
for i,b in enumerate(blobs):
|
||||
x0,y0,x1,y1,area = b
|
||||
print(i, 'blob box (vstrip coords)=', (x0,y0,x1,y1), 'area=',area)
|
||||
# extract blob images
|
||||
def extract_from_rows(rr, x0,y0,x1,y1):
|
||||
w = x1-x0+1; h = y1-y0+1
|
||||
img = [[rr[y+y0][x+x0] for x in range(w)] for y in range(h)]
|
||||
return img
|
||||
blob_imgs = [extract_from_rows(vrows, *b[:4]) for b in blobs]
|
||||
# template match each blob against hud with sliding window
|
||||
import math
|
||||
results = []
|
||||
for bi, img in enumerate(blob_imgs):
|
||||
bh = len(img); bw = len(img[0])
|
||||
if bh<4 or bw<4: continue
|
||||
best = (1e12, -1,-1)
|
||||
# convert flattened arrays for speed
|
||||
tmpl = [c for row in img for px in row for c in px]
|
||||
for y in range(0, h-bh+1):
|
||||
for x in range(0, w-bw+1):
|
||||
ssd=0
|
||||
for j in range(bh):
|
||||
for i in range(bw):
|
||||
r1,g1,b1 = img[j][i]
|
||||
r2,g2,b2 = hud[j+y][i+x]
|
||||
dr=r1-r2; dg=g1-g2; db=b1-b2
|
||||
ssd += dr*dr + dg*dg + db*db
|
||||
if ssd>best[0]: break
|
||||
if ssd>best[0]: break
|
||||
if ssd < best[0]: best = (ssd,x,y)
|
||||
results.append((bi,bw,bh,best[0],best[1],best[2]))
|
||||
# sort by score
|
||||
results.sort(key=lambda x: x[3])
|
||||
print('\nTop matches:')
|
||||
for bi,bw,bh,ssd,x,y in results[:10]:
|
||||
# compute HUD pixel coordinates and vram offsets
|
||||
hud_x = lx + x; hud_y = ty + y
|
||||
start_idx = hud_y*W + hud_x
|
||||
end_idx = (hud_y+bh-1)*W + (hud_x + bw -1)
|
||||
so = start_idx*2; eo = (end_idx+1)*2 -1
|
||||
vb = blobs[bi]
|
||||
v_x0 = vx0 + vb[0]; v_y0 = vb[1]; v_x1 = vx0 + vb[2]; v_y1 = vb[3]
|
||||
print(f'blob#{bi} vbox=({v_x0},{v_y0})-({v_x1},{v_y1}) size={bw}x{bh} bestssd={ssd} hudpos=({hud_x},{hud_y}) bytes=0x{so:06x}-0x{eo:06x}')
|
||||
|
||||
# If results empty, report
|
||||
if not results:
|
||||
print('No matches found')
|
||||
Loading…
Add table
Add a link
Reference in a new issue