60 lines
2 KiB
Python
60 lines
2 KiB
Python
|
|
from collections import deque
|
||
|
|
IN_PATH = r"K:\ghidra\Crusader_Decomp\binary\Crusader - No Remorse Memdump Weapons.bin"
|
||
|
|
W,H = 1024,512
|
||
|
|
import os
|
||
|
|
with open(IN_PATH,'rb') as f:
|
||
|
|
data = f.read()
|
||
|
|
count = min(len(data)//2, W*H)
|
||
|
|
# build mask of non-black pixels
|
||
|
|
mask = bytearray(W*H)
|
||
|
|
for i in range(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
|
||
|
|
if r|g|b:
|
||
|
|
mask[i] = 1
|
||
|
|
# flood-fill connected components (4-neigh)
|
||
|
|
visited = bytearray(W*H)
|
||
|
|
bbs = []
|
||
|
|
for idx in range(W*H):
|
||
|
|
if mask[idx] and not visited[idx]:
|
||
|
|
q = deque([idx])
|
||
|
|
visited[idx]=1
|
||
|
|
xs = []
|
||
|
|
ys = []
|
||
|
|
while q:
|
||
|
|
v = q.popleft()
|
||
|
|
y = v // W
|
||
|
|
x = v % W
|
||
|
|
xs.append(x); ys.append(y)
|
||
|
|
# neighbors
|
||
|
|
for dx,dy in ((1,0),(-1,0),(0,1),(0,-1)):
|
||
|
|
nx = x+dx; ny = y+dy
|
||
|
|
if 0<=nx<W and 0<=ny<H:
|
||
|
|
ni = ny*W+nx
|
||
|
|
if mask[ni] and not visited[ni]:
|
||
|
|
visited[ni]=1
|
||
|
|
q.append(ni)
|
||
|
|
x0,x1 = min(xs), max(xs)
|
||
|
|
y0,y1 = min(ys), max(ys)
|
||
|
|
area = len(xs)
|
||
|
|
start_idx = y0*W + x0
|
||
|
|
end_idx = y1*W + x1
|
||
|
|
start_off = start_idx*2
|
||
|
|
end_off = (end_idx+1)*2 - 1
|
||
|
|
bbs.append((x0,y0,x1,y1,area,start_off,end_off))
|
||
|
|
# sort by area descending
|
||
|
|
bbs.sort(key=lambda x: -x[4])
|
||
|
|
print('Found', len(bbs), 'components')
|
||
|
|
for i,(x0,y0,x1,y1,area,so,eo) in enumerate(bbs[:20]):
|
||
|
|
print(f'[{i}] box=({x0},{y0})-({x1},{y1}) area={area} bytes=0x{so:06x}-0x{eo:06x}')
|
||
|
|
# Save the top few as small BMP crops for inspection
|
||
|
|
from PIL import Image
|
||
|
|
img = Image.open(r"K:\ghidra\Crusader_Decomp\binary\vram_weapons.png")
|
||
|
|
for i,(x0,y0,x1,y1,area,so,eo) in enumerate(bbs[:12]):
|
||
|
|
crop = img.crop((x0,y0,x1+1,y1+1))
|
||
|
|
out = r"K:\ghidra\Crusader_Decomp\binary\crop_%02d.png"%i
|
||
|
|
crop.save(out)
|
||
|
|
print('wrote', out)
|