"""Extract the installed original galaxy UI movies for read-only offline research."""
import hashlib
import importlib.util
import json
import re
import struct
import sys
import zlib
from pathlib import Path
spec=importlib.util.spec_from_file_location('assets','research/galaxy_asset_inventory.py')
saved=sys.argv
sys.argv=['extract','artifacts/galaxy-marker-research/unused.json']
assets=importlib.util.module_from_spec(spec)
spec.loader.exec_module(assets)
sys.argv=saved
out=Path('artifacts/galaxy-marker-research')
out.mkdir(exist_ok=True)
rows=[]
for name,key in [('labels','09dae208be9a2d0f360ff77bcacbeab20993e90b'),('ui','79a752f20cbfb28917345f272b01292ceede1e1f'),('map','b07939840732555d1c406de6aba3652c6199197d')]:
source=assets.ROOT/('0'+key[0])/key
fres=assets.decode(source)
(out/(name+'.fres')).write_bytes(fres)
for match in re.finditer(rb'\x78[\x01\x9c\xda]',fres):
try:
decoder=zlib.decompressobj()
body=decoder.decompress(fres[match.start():],128*1024*1024)
if not decoder.eof or b'CFX' not in body:continue
except zlib.error:continue
break
else:raise ValueError('Original UI body not found: '+name)
(out/(name+'.bin')).write_bytes(body)
at=body.index(b'CFX')
decoder=zlib.decompressobj()
movie_body=decoder.decompress(body[at+8:])
if not decoder.eof:raise ValueError('Truncated original movie: '+name)
consumed=len(body)-at-8-len(decoder.unused_data)
compressed=body[at:at+8+consumed]
(out/(name+'.gfx')).write_bytes(compressed)
# Decode original Scaleform CFX to the corresponding FWS container only.
# Every tag, path, colour, frame label and ActionScript byte remains intact.
movie=b'FWS'+body[at+3:at+8]+movie_body
(out/(name+'.swf')).write_bytes(movie)
rows.append(dict(name=name,resourceHash=key,source=str(source),sourceSha256=hashlib.sha256(source.read_bytes()).hexdigest(),
gfxSha256=hashlib.sha256(compressed).hexdigest(),movieSha256=hashlib.sha256(movie).hexdigest(),
originalGfxOffset=at,declaredLength=struct.unpack_from('<I',movie,4)[0],decodedLength=len(movie),
note='CFX to FWS signature and decompression only; declared original length retained'))
(out/'resources.json').write_text(json.dumps(rows,indent=2)+'\n',encoding='utf-8')
print(json.dumps(rows,indent=2))
"""Extract the installed original galaxy UI movies for read-only offline research."""
import hashlib
import importlib.util
import json
import re
import struct
import sys
import zlib
from pathlib import Path
spec=importlib.util.spec_from_file_location('assets','research/galaxy_asset_inventory.py')
saved=sys.argv
sys.argv=['extract','artifacts/galaxy-marker-research/unused.json']
assets=importlib.util.module_from_spec(spec)
spec.loader.exec_module(assets)
sys.argv=saved
out=Path('artifacts/galaxy-marker-research')
out.mkdir(exist_ok=True)
rows=[]
for name,key in [('labels','09dae208be9a2d0f360ff77bcacbeab20993e90b'),('ui','79a752f20cbfb28917345f272b01292ceede1e1f'),('map','b07939840732555d1c406de6aba3652c6199197d')]:
source=assets.ROOT/('0'+key[0])/key
fres=assets.decode(source)
(out/(name+'.fres')).write_bytes(fres)
for match in re.finditer(rb'\x78[\x01\x9c\xda]',fres):
try:
decoder=zlib.decompressobj()
body=decoder.decompress(fres[match.start():],128*1024*1024)
if not decoder.eof or b'CFX' not in body:continue
except zlib.error:continue
break
else:raise ValueError('Original UI body not found: '+name)
(out/(name+'.bin')).write_bytes(body)
at=body.index(b'CFX')
decoder=zlib.decompressobj()
movie_body=decoder.decompress(body[at+8:])
if not decoder.eof:raise ValueError('Truncated original movie: '+name)
consumed=len(body)-at-8-len(decoder.unused_data)
compressed=body[at:at+8+consumed]
(out/(name+'.gfx')).write_bytes(compressed)
# Decode original Scaleform CFX to the corresponding FWS container only.
# Every tag, path, colour, frame label and ActionScript byte remains intact.
movie=b'FWS'+body[at+3:at+8]+movie_body
(out/(name+'.swf')).write_bytes(movie)
rows.append(dict(name=name,resourceHash=key,source=str(source),sourceSha256=hashlib.sha256(source.read_bytes()).hexdigest(),
gfxSha256=hashlib.sha256(compressed).hexdigest(),movieSha256=hashlib.sha256(movie).hexdigest(),
originalGfxOffset=at,declaredLength=struct.unpack_from('<I',movie,4)[0],decodedLength=len(movie),
note='CFX to FWS signature and decompression only; declared original length retained'))
(out/'resources.json').write_text(json.dumps(rows,indent=2)+'\n',encoding='utf-8')
print(json.dumps(rows,indent=2))