107 lines
3.8 KiB
Python
107 lines
3.8 KiB
Python
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')
|