import struct, zlib, os IN_BIN = r"K:\ghidra\Crusader_Decomp\binary\Crusader - No Remorse Memdump Weapons.bin" IN_PNG = r"K:\ghidra\Crusader_Decomp\binary\vram_weapons.png" W,H = 1024,512 # simple PNG crop writer: read full PNG rows from our previous generated PNG file # read raw image bytes (we will load via simple approach using original binary->RGB conversion again) with open(IN_BIN,'rb') as f: data = f.read() count = min(len(data)//2, W*H) # make full RGB array rows = [] for y in range(H): row = bytearray() 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.extend([r,g,b]) rows.append(bytes(row)) # crop grid params xs = list(range(0, W, 128)) ys = list(range(0, 192, 64)) out_dir = r"K:\ghidra\Crusader_Decomp\binary\crops_grid" os.makedirs(out_dir, exist_ok=True) import zlib, struct for y0 in ys: for x0 in xs: w = min(256, W-x0) h = min(128, H-y0) # build raw rows top-to-bottom rawrows = [] for y in range(y0, y0+h): rawrows.append(b"\x00" + rows[y][x0*3:(x0+w)*3]) raw = b"".join(rawrows) comp = zlib.compress(raw, level=9) def chunk(t,d): out = struct.pack('>I', len(d)) + t + d import zlib crc = zlib.crc32(t + d) & 0xffffffff out += struct.pack('>I', crc) return out png = b"\x89PNG\r\n\x1a\n" png += chunk(b'IHDR', struct.pack('>IIBBBBB', w, h, 8, 2, 0, 0, 0)) png += chunk(b'IDAT', comp) png += chunk(b'IEND', b'') out = os.path.join(out_dir, f'crop_{x0}_{y0}.png') with open(out,'wb') as f: f.write(png) # compute file-offset range start_idx = y0*W + x0 end_idx = (y0+h-1)*W + (x0+w-1) so = start_idx*2 eo = (end_idx+1)*2 -1 print(out, f'box=({x0},{y0})-({x0+w-1},{y0+h-1}) bytes=0x{so:06x}-0x{eo:06x}')