mirror of
https://github.com/elliotnunn/tbxi.git
synced 2024-06-16 00:29:37 +00:00
61 lines
1.8 KiB
Python
61 lines
1.8 KiB
Python
|
# Routines to fiddle with 'cfrg' (Code Fragment) metadata resources
|
||
|
|
||
|
# These are required only because the code fragments
|
||
|
# referenced by a cfrg are usually at specific offsets
|
||
|
# in a data fork, rather than in a resource. When we
|
||
|
# manipulate a data fork, any corresponding cfrg must be
|
||
|
# adjusted accordingly. This un-Mac-like scheme originated
|
||
|
# as a way to allow code fragments to be memory-mapped,
|
||
|
# which is impossible in a frequently-repacked resource fork.
|
||
|
|
||
|
|
||
|
import struct
|
||
|
|
||
|
|
||
|
# Internal: where are the fields that must be edited?
|
||
|
def get_dfrkoffset_field_positions(cfrg):
|
||
|
# old-style cfrg only, seems to work fine...
|
||
|
entry_cnt, = struct.unpack_from('>L', cfrg, 28)
|
||
|
|
||
|
ctr = 32
|
||
|
|
||
|
for i in range(entry_cnt):
|
||
|
if len(cfrg) < ctr + 43: break
|
||
|
|
||
|
if cfrg[ctr + 23] == 1: # kDataForkCFragLocator
|
||
|
yield ctr + 24
|
||
|
|
||
|
ctr += 42 + 1 + cfrg[ctr + 42]
|
||
|
while ctr % 4: ctr += 1
|
||
|
|
||
|
|
||
|
# Tell this resource that you moved the PEFs that it references in the data fork
|
||
|
def adjust_dfrkoffset_fields(cfrg, delta):
|
||
|
cfrg = bytearray(cfrg)
|
||
|
|
||
|
for field in get_dfrkoffset_field_positions(cfrg):
|
||
|
ofs, = struct.unpack_from('>L', cfrg, field)
|
||
|
ofs += delta
|
||
|
struct.pack_into('>L', cfrg, field, ofs)
|
||
|
|
||
|
return bytes(cfrg)
|
||
|
|
||
|
|
||
|
# Get the (start, stop) offset range of PEFs in the data fork
|
||
|
def get_dfrk_range(cfrg_list, dfrk_len):
|
||
|
left = dfrk_len
|
||
|
right = 0
|
||
|
|
||
|
for cfrg in cfrg_list:
|
||
|
for field in get_dfrkoffset_field_positions(cfrg):
|
||
|
my_left, = struct.unpack_from('>L', cfrg, field)
|
||
|
left = min(my_left, left)
|
||
|
|
||
|
my_right, = struct.unpack_from('>L', cfrg, field + 4)
|
||
|
if my_right == 0:
|
||
|
right = dfrk_len
|
||
|
else:
|
||
|
right = max(right, my_left + my_right)
|
||
|
|
||
|
return left, right
|