mirror of
https://github.com/elliotnunn/ToolboxToolbox.git
synced 2024-12-27 03:32:25 +00:00
Add sundry utilities
This commit is contained in:
parent
c0b5bc5a39
commit
72c8716b63
5
BootScriptExtractor.sh
Executable file
5
BootScriptExtractor.sh
Executable file
@ -0,0 +1,5 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
# USAGE: BootScriptExtractor <ROM >BOOTSCRIPT
|
||||||
|
|
||||||
|
head -c $((0x4000)) | LC_CTYPE=C tr -d '\0' | LC_CTYPE=C tr '\r' '\n' | awk 'f && /BOOT-SCRIPT/{exit} f{print} /BOOT-SCRIPT/{f=1}' | sed 's/# ...... const/# xxxxxx const/'
|
161
Every68kInstAssembler.py
Executable file
161
Every68kInstAssembler.py
Executable file
@ -0,0 +1,161 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
|
||||||
|
import struct
|
||||||
|
from sys import argv
|
||||||
|
|
||||||
|
class MPWObject:
|
||||||
|
def __init__(self):
|
||||||
|
self._list = []
|
||||||
|
self._dict = []
|
||||||
|
self._backdict = {}
|
||||||
|
self._dict_idx = 200
|
||||||
|
|
||||||
|
def __bytes__(self):
|
||||||
|
dest = bytearray()
|
||||||
|
|
||||||
|
for chunk in self._list:
|
||||||
|
dest.extend(chunk)
|
||||||
|
if len(dest) & 1: dest.append(0)
|
||||||
|
|
||||||
|
return bytes(dest)
|
||||||
|
|
||||||
|
def _ensurename(self, name):
|
||||||
|
# get the ID of this name from the dict
|
||||||
|
# If nonexistent, then add it
|
||||||
|
# i.e. idempotent
|
||||||
|
|
||||||
|
try:
|
||||||
|
return self._backdict[name]
|
||||||
|
except KeyError:
|
||||||
|
self.putdict([name])
|
||||||
|
return self._backdict[name]
|
||||||
|
|
||||||
|
def _quickappend(self, *bytelist):
|
||||||
|
self._list.append(bytes(bytelist))
|
||||||
|
|
||||||
|
def putfirst(self):
|
||||||
|
self._quickappend(1, 1, 0, 2)
|
||||||
|
|
||||||
|
def putlast(self):
|
||||||
|
self._quickappend(2, 0)
|
||||||
|
|
||||||
|
def putdict(self, items):
|
||||||
|
dest = bytearray()
|
||||||
|
|
||||||
|
dest.extend([4, 0, 99, 99])
|
||||||
|
dest.extend(struct.pack('>H', self._dict_idx))
|
||||||
|
|
||||||
|
flag = False
|
||||||
|
|
||||||
|
for item in items:
|
||||||
|
flag = True
|
||||||
|
dest.append(len(item))
|
||||||
|
dest.extend(item.encode('ascii'))
|
||||||
|
|
||||||
|
self._backdict[item] = self._dict_idx
|
||||||
|
|
||||||
|
self._dict_idx += 1 # ID of the *next* thing
|
||||||
|
|
||||||
|
if not flag: return
|
||||||
|
|
||||||
|
struct.pack_into('>H', dest, 2, len(dest))
|
||||||
|
|
||||||
|
self._list.append(dest)
|
||||||
|
|
||||||
|
def putmod(self, name='#0001', segname='Main', flags=(1<<7)+(1<<3)):
|
||||||
|
modid = self._ensurename(name)
|
||||||
|
segid = self._ensurename(segname)
|
||||||
|
self._last_mod_id = modid
|
||||||
|
|
||||||
|
self._list.append(struct.pack('>BBHH', 5, flags, modid, segid))
|
||||||
|
|
||||||
|
def putentry(self, offset, name):
|
||||||
|
entid = self._ensurename(name)
|
||||||
|
|
||||||
|
self._list.append(struct.pack('>BBHL', 6, 1<<3, entid, offset))
|
||||||
|
|
||||||
|
def putsize(self, size):
|
||||||
|
self._list.append(struct.pack('>BBL', 7, 0, size))
|
||||||
|
|
||||||
|
def putcontents(self, data): # in multiple chunks please!
|
||||||
|
done = 0
|
||||||
|
|
||||||
|
while done < len(data):
|
||||||
|
this_time = data[done:done+30000]
|
||||||
|
|
||||||
|
header = struct.pack('>BBHL', 8, 1<<3, 8 + len(this_time), done)
|
||||||
|
|
||||||
|
self._list.append(header + this_time)
|
||||||
|
|
||||||
|
done += len(this_time)
|
||||||
|
|
||||||
|
def putcomment(self, cmt):
|
||||||
|
cmt = cmt.replace('\n','\r').encode('mac_roman')
|
||||||
|
if len(cmt) & 1: cmt += b' '
|
||||||
|
|
||||||
|
dest = bytearray()
|
||||||
|
dest.extend([3, 0])
|
||||||
|
dest.extend(struct.pack('>H', len(cmt) + 4))
|
||||||
|
dest.extend(cmt)
|
||||||
|
|
||||||
|
self._list.append(dest)
|
||||||
|
|
||||||
|
def putsimpleref(self, targname, width, *offsets):
|
||||||
|
offsets = list(offsets)
|
||||||
|
|
||||||
|
if width == 2: # of the operand field, in bytes
|
||||||
|
flags = 1 << 4
|
||||||
|
elif width == 4:
|
||||||
|
flags = 0
|
||||||
|
|
||||||
|
flags |= 1<<3 # longwords in the offset list!
|
||||||
|
|
||||||
|
targid = self._ensurename(targname)
|
||||||
|
|
||||||
|
dest = struct.pack('>BBHH', 9, flags, 6 + 4 * len(offsets), targid)
|
||||||
|
dest += b''.join(struct.pack('>L', o) for o in offsets)
|
||||||
|
|
||||||
|
self._list.append(dest)
|
||||||
|
|
||||||
|
def putweirdref(self, targname, width, *offsets):
|
||||||
|
# Assumes that you've already put -offset at offset
|
||||||
|
offsets = list(offsets)
|
||||||
|
|
||||||
|
if width == 1:
|
||||||
|
flags = 2 << 4
|
||||||
|
elif width == 2: # of the operand field, in bytes
|
||||||
|
flags = 1 << 4
|
||||||
|
elif width == 4:
|
||||||
|
flags = 0 << 4
|
||||||
|
|
||||||
|
flags |= 1<<7 # difference calculation
|
||||||
|
# flags |= 1<<3 # longwords in the offset list!
|
||||||
|
|
||||||
|
targid = self._ensurename(targname)
|
||||||
|
|
||||||
|
dest = struct.pack('>BBHHH', 10, flags, 8 + 2 * len(offsets), targid, self._last_mod_id)
|
||||||
|
dest += b''.join(struct.pack('>H', o) for o in offsets)
|
||||||
|
|
||||||
|
self._list.append(dest)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# included my own copy of mpwobj!
|
||||||
|
|
||||||
|
o = MPWObject()
|
||||||
|
|
||||||
|
o.putfirst()
|
||||||
|
|
||||||
|
for i in range(65536):
|
||||||
|
b = struct.pack('>H16b', i, *range(1,17))
|
||||||
|
|
||||||
|
o.putmod(name='#xxxx')
|
||||||
|
o.putcontents(b)
|
||||||
|
|
||||||
|
o.putlast()
|
||||||
|
|
||||||
|
if argv[1:]:
|
||||||
|
with open(argv[1], 'wb') as f:
|
||||||
|
f.write(bytes(o))
|
||||||
|
|
35
KernelExtractor.py
Executable file
35
KernelExtractor.py
Executable file
@ -0,0 +1,35 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
|
||||||
|
from sys import argv
|
||||||
|
|
||||||
|
# USAGE: KernelExtractor.py DESTDIR ROM1 [ROM2 ...]
|
||||||
|
|
||||||
|
kerns = {}
|
||||||
|
|
||||||
|
for fname in argv[2:]:
|
||||||
|
print(fname)
|
||||||
|
with open(fname, 'rb') as f:
|
||||||
|
b = f.read()
|
||||||
|
if len(b) != 0x400000: print('--- bad size')
|
||||||
|
b = b[0x310000:]
|
||||||
|
l = b.index(bytes(1024))
|
||||||
|
l += 3
|
||||||
|
l -= l % 4
|
||||||
|
b = b[:l]
|
||||||
|
if not b:
|
||||||
|
print('--- no kernel')
|
||||||
|
continue
|
||||||
|
vers = '%02x%02x' % tuple(b[4:6])
|
||||||
|
if not vers.startswith('02'): continue
|
||||||
|
print('---', vers)
|
||||||
|
if vers in kerns:
|
||||||
|
if kerns[vers] != b:
|
||||||
|
print('--- bad motivator')
|
||||||
|
kerns[vers] = None
|
||||||
|
else:
|
||||||
|
kerns[vers] = b
|
||||||
|
|
||||||
|
for v, k in kerns.items():
|
||||||
|
if k is None: continue
|
||||||
|
with open(argv[1] + v, 'wb') as f:
|
||||||
|
f.write(k)
|
71
MovePEFsToResources.py
Executable file
71
MovePEFsToResources.py
Executable file
@ -0,0 +1,71 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
|
||||||
|
# MacOS apps, extensions etc often keep their PEF (Portable Executable
|
||||||
|
# Format) binaries (also called Code Fragments) in the data fork, with
|
||||||
|
# offsets in a 'cfrg' resource in the resource fork. This scheme allows
|
||||||
|
# the Code Fragment Manager to map that file directly into memory (when VM
|
||||||
|
# is on) instead of using the Resource Manager to load it into a Memory
|
||||||
|
# Manager heap. But when multiple PEFs are concatenated into the DF,
|
||||||
|
# patchpef (https://github.com/elliotnunn/patchpef) cannot be used to
|
||||||
|
# mangle them. This script moves the PEFs to 'ndrv' resources (type
|
||||||
|
# doesn't really matter) and updates the 'cfrg' accordingly. The original
|
||||||
|
# PEFs are zeroed out in the data fork, so if everything has gone
|
||||||
|
# correctly, the data fork should be all zeroes.
|
||||||
|
|
||||||
|
# USAGE: MovePEFsToResources.py SRCFILE DESTFILE
|
||||||
|
|
||||||
|
from sys import argv
|
||||||
|
from subprocess import run
|
||||||
|
|
||||||
|
oln, fn = argv[1:]
|
||||||
|
|
||||||
|
run(['rm', '-f', fn])
|
||||||
|
run(['cp', oln, fn])
|
||||||
|
|
||||||
|
with open(fn, 'rb') as f:
|
||||||
|
df = bytearray(f.read())
|
||||||
|
|
||||||
|
run(['zcp', fn+'//cfrg/0', '/tmp/mycfrg'])
|
||||||
|
|
||||||
|
with open('/tmp/mycfrg', 'rb') as f:
|
||||||
|
cfrg = bytearray(f.read())
|
||||||
|
|
||||||
|
pwpc_locs = []
|
||||||
|
start = 0
|
||||||
|
while True:
|
||||||
|
found = cfrg.find(b'pwpc', start)
|
||||||
|
if found == -1: break
|
||||||
|
pwpc_locs.append(found)
|
||||||
|
start = found + 4
|
||||||
|
|
||||||
|
for i, p in enumerate(pwpc_locs):
|
||||||
|
where = cfrg[p+0x14+3]
|
||||||
|
if where != 1: continue
|
||||||
|
|
||||||
|
rsrcnum = i+13000
|
||||||
|
|
||||||
|
start = int.from_bytes(cfrg[p+0x18:p+0x1c], 'big')
|
||||||
|
size = int.from_bytes(cfrg[p+0x1c:p+0x20], 'big')
|
||||||
|
nlen = cfrg[p+0x2a]
|
||||||
|
name = cfrg[p+0x2b:p+0x2b+nlen].decode('ascii')
|
||||||
|
|
||||||
|
pef = df[start:start+size]
|
||||||
|
|
||||||
|
with open('/tmp/thispef', 'wb') as f:
|
||||||
|
f.write(pef)
|
||||||
|
|
||||||
|
run(['zcp', '/tmp/thispef', '%s//ndrv/%d/%s/sysheap/locked' % (fn, rsrcnum, name)])
|
||||||
|
|
||||||
|
df[start:start+size] = bytes(size)
|
||||||
|
|
||||||
|
cfrg[p+0x14+3] = 2
|
||||||
|
cfrg[p+0x18:p+0x1c] = b'ndrv'
|
||||||
|
cfrg[p+0x1c:p+0x20] = rsrcnum.to_bytes(4, 'big', signed=True)
|
||||||
|
|
||||||
|
with open(fn, 'wb') as f:
|
||||||
|
f.write(df)
|
||||||
|
|
||||||
|
with open('/tmp/mycfrg', 'wb') as f:
|
||||||
|
f.write(cfrg)
|
||||||
|
|
||||||
|
run(['zcp', '/tmp/mycfrg', fn+'//cfrg/0'])
|
Loading…
Reference in New Issue
Block a user