├── rom ├── pef ├── ndrv │ ├── i2c │ ├── cardbus │ ├── display │ ├── firewire │ ├── ata │ │ ├── cmd646 │ │ ├── kauai │ │ ├── heathrow │ │ └── keylargo │ ├── nvram │ │ ├── flash │ │ ├── mac-io │ │ └── via-pmu │ ├── rtc │ │ ├── via-cuda │ │ └── via-pmu │ ├── BacklightDriver │ └── PowerMgrPlugin │ │ ├── pmu │ │ ├── cuda │ │ ├── pmu-2000 │ │ └── pmu-99 ├── nlib │ ├── AGPLib │ ├── DFMLib │ ├── DevNLib │ ├── PMULib │ ├── PCCardLib │ ├── FWServicesLib │ ├── EtherPrintfLib │ ├── RTCServicesLib │ ├── TimeManagerLib │ ├── NVRAMServicesLib │ ├── NativePowerMgrLib │ ├── GenericDriverFamily │ └── PCICyclesLib │ │ ├── Grackle │ │ └── UniNorth └── shlb │ ├── StartLib │ └── lanLib │ ├── bmac+ │ ├── gmac │ └── apple21143 ├── trampoline.elf ├── .gitignore ├── scripts ├── lzss.py ├── binhexmake.py ├── prclmake.py ├── prcltool.py └── bootmake.py ├── README.md ├── Makefile ├── parcel-layout.txt └── lzss.c /rom: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/elliotnunn/newworld-rom/HEAD/rom -------------------------------------------------------------------------------- /pef/ndrv/i2c: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/elliotnunn/newworld-rom/HEAD/pef/ndrv/i2c -------------------------------------------------------------------------------- /trampoline.elf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/elliotnunn/newworld-rom/HEAD/trampoline.elf -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | parcels 3 | tbxi 4 | lzss 5 | __pycache__ 6 | *.patch 7 | *.hqx 8 | -------------------------------------------------------------------------------- /pef/ndrv/cardbus: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/elliotnunn/newworld-rom/HEAD/pef/ndrv/cardbus -------------------------------------------------------------------------------- /pef/ndrv/display: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/elliotnunn/newworld-rom/HEAD/pef/ndrv/display -------------------------------------------------------------------------------- /pef/ndrv/firewire: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/elliotnunn/newworld-rom/HEAD/pef/ndrv/firewire -------------------------------------------------------------------------------- /pef/nlib/AGPLib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/elliotnunn/newworld-rom/HEAD/pef/nlib/AGPLib -------------------------------------------------------------------------------- /pef/nlib/DFMLib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/elliotnunn/newworld-rom/HEAD/pef/nlib/DFMLib -------------------------------------------------------------------------------- /pef/nlib/DevNLib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/elliotnunn/newworld-rom/HEAD/pef/nlib/DevNLib -------------------------------------------------------------------------------- /pef/nlib/PMULib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/elliotnunn/newworld-rom/HEAD/pef/nlib/PMULib -------------------------------------------------------------------------------- /pef/shlb/StartLib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/elliotnunn/newworld-rom/HEAD/pef/shlb/StartLib -------------------------------------------------------------------------------- /pef/ndrv/ata/cmd646: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/elliotnunn/newworld-rom/HEAD/pef/ndrv/ata/cmd646 -------------------------------------------------------------------------------- /pef/ndrv/ata/kauai: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/elliotnunn/newworld-rom/HEAD/pef/ndrv/ata/kauai -------------------------------------------------------------------------------- /pef/nlib/PCCardLib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/elliotnunn/newworld-rom/HEAD/pef/nlib/PCCardLib -------------------------------------------------------------------------------- /pef/ndrv/ata/heathrow: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/elliotnunn/newworld-rom/HEAD/pef/ndrv/ata/heathrow -------------------------------------------------------------------------------- /pef/ndrv/ata/keylargo: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/elliotnunn/newworld-rom/HEAD/pef/ndrv/ata/keylargo -------------------------------------------------------------------------------- /pef/ndrv/nvram/flash: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/elliotnunn/newworld-rom/HEAD/pef/ndrv/nvram/flash -------------------------------------------------------------------------------- /pef/ndrv/nvram/mac-io: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/elliotnunn/newworld-rom/HEAD/pef/ndrv/nvram/mac-io -------------------------------------------------------------------------------- /pef/ndrv/nvram/via-pmu: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/elliotnunn/newworld-rom/HEAD/pef/ndrv/nvram/via-pmu -------------------------------------------------------------------------------- /pef/ndrv/rtc/via-cuda: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/elliotnunn/newworld-rom/HEAD/pef/ndrv/rtc/via-cuda -------------------------------------------------------------------------------- /pef/ndrv/rtc/via-pmu: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/elliotnunn/newworld-rom/HEAD/pef/ndrv/rtc/via-pmu -------------------------------------------------------------------------------- /pef/nlib/FWServicesLib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/elliotnunn/newworld-rom/HEAD/pef/nlib/FWServicesLib -------------------------------------------------------------------------------- /pef/shlb/lanLib/bmac+: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/elliotnunn/newworld-rom/HEAD/pef/shlb/lanLib/bmac+ -------------------------------------------------------------------------------- /pef/shlb/lanLib/gmac: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/elliotnunn/newworld-rom/HEAD/pef/shlb/lanLib/gmac -------------------------------------------------------------------------------- /pef/ndrv/BacklightDriver: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/elliotnunn/newworld-rom/HEAD/pef/ndrv/BacklightDriver -------------------------------------------------------------------------------- /pef/nlib/EtherPrintfLib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/elliotnunn/newworld-rom/HEAD/pef/nlib/EtherPrintfLib -------------------------------------------------------------------------------- /pef/nlib/RTCServicesLib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/elliotnunn/newworld-rom/HEAD/pef/nlib/RTCServicesLib -------------------------------------------------------------------------------- /pef/nlib/TimeManagerLib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/elliotnunn/newworld-rom/HEAD/pef/nlib/TimeManagerLib -------------------------------------------------------------------------------- /pef/ndrv/PowerMgrPlugin/pmu: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/elliotnunn/newworld-rom/HEAD/pef/ndrv/PowerMgrPlugin/pmu -------------------------------------------------------------------------------- /pef/nlib/NVRAMServicesLib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/elliotnunn/newworld-rom/HEAD/pef/nlib/NVRAMServicesLib -------------------------------------------------------------------------------- /pef/nlib/NativePowerMgrLib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/elliotnunn/newworld-rom/HEAD/pef/nlib/NativePowerMgrLib -------------------------------------------------------------------------------- /pef/shlb/lanLib/apple21143: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/elliotnunn/newworld-rom/HEAD/pef/shlb/lanLib/apple21143 -------------------------------------------------------------------------------- /pef/ndrv/PowerMgrPlugin/cuda: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/elliotnunn/newworld-rom/HEAD/pef/ndrv/PowerMgrPlugin/cuda -------------------------------------------------------------------------------- /pef/nlib/GenericDriverFamily: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/elliotnunn/newworld-rom/HEAD/pef/nlib/GenericDriverFamily -------------------------------------------------------------------------------- /pef/nlib/PCICyclesLib/Grackle: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/elliotnunn/newworld-rom/HEAD/pef/nlib/PCICyclesLib/Grackle -------------------------------------------------------------------------------- /pef/ndrv/PowerMgrPlugin/pmu-2000: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/elliotnunn/newworld-rom/HEAD/pef/ndrv/PowerMgrPlugin/pmu-2000 -------------------------------------------------------------------------------- /pef/ndrv/PowerMgrPlugin/pmu-99: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/elliotnunn/newworld-rom/HEAD/pef/ndrv/PowerMgrPlugin/pmu-99 -------------------------------------------------------------------------------- /pef/nlib/PCICyclesLib/UniNorth: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/elliotnunn/newworld-rom/HEAD/pef/nlib/PCICyclesLib/UniNorth -------------------------------------------------------------------------------- /scripts/lzss.py: -------------------------------------------------------------------------------- 1 | import os.path 2 | import subprocess as sp 3 | 4 | def _run(arg, input): 5 | lzbin = os.path.join(os.path.dirname(__file__), 'lzss') 6 | p = sp.Popen([lzbin, arg], stdin=sp.PIPE, stdout=sp.PIPE, bufsize=0x400000) 7 | output, stderr = p.communicate(input) 8 | return output 9 | 10 | def compress(data): 11 | return _run('c', data) 12 | 13 | def extract(data): 14 | return _run('x', data) 15 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | The NewWorld ROM 2 | ================ 3 | 4 | This repo is part of the *CDG5* project. It builds version 9.6.1 of the *parcels*-based Mac OS ROM file, starting from a 4 MB Power Mac ROM (`rom`) and other PEF binaries (`pef/`). Use https://github.com/elliotnunn/powermac-rom to build your own ROM. A few bytes are different from the original file because (I think) the original Apple build tool failed to zero-initialize a buffer. The build result does not contain the *System Enabler* found in later Mac OS ROM versions. 5 | 6 | Building 7 | -------- 8 | 9 | A basic Unix toolchain is required. 10 | 11 | make tbxi.hqx 12 | 13 | Instead of using the included 4 MB ROM, you can uncomment some code in the makefile to trigger a build from https://github.com/elliotnunn/powermac-rom 14 | 15 | The makefile also helps you to test your build: 16 | 17 | make test-qemu 18 | make test-fw 19 | 20 | Patching 21 | -------- 22 | 23 | Some useful patches to the Open Firmware boot script can be enabled at the top of `bootmake.py`. 24 | 25 | The parcel build script will preferentially load files with `.patch` appended to the name. This is helpful when using https://github.com/elliotnunn/patchpef to edit the PowerPC binaries under `pef/`. For example, to prevent the Power Manager from crashing while trying to load a PMU plugin on the Mac mini: 26 | 27 | patchpef.py pef/nlib/NativePowerMgrLib{,.patch} Initialize+0x94 " li r3,0" 28 | -------------------------------------------------------------------------------- /scripts/binhexmake.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | 4 | import binhex 5 | import argparse 6 | import os.path 7 | 8 | 9 | def get_file(filename): 10 | with open(filename, 'rb') as f: 11 | return f.read() 12 | 13 | 14 | def fourcc(s): 15 | b = s.encode('ascii').ljust(4, b' ') 16 | if len(b) != 4: 17 | raise ValueError('wrong length') 18 | return b 19 | 20 | 21 | parser = argparse.ArgumentParser( 22 | description = """Blah.""" 23 | ) 24 | 25 | parser.add_argument('--data', action='store', metavar='FILE', help='Data fork') 26 | parser.add_argument('--rsrc', action='store', metavar='FILE', help='Resource fork') 27 | parser.add_argument('--type', action='store', metavar='FOURCC', type=fourcc, default=' ', help='(space-padded) type code') 28 | parser.add_argument('--creator', action='store', metavar='FOURCC', type=fourcc, default=' ', help='(space-padded) creator code') 29 | parser.add_argument('--name', action='store', metavar='FILENAME', default='', help='archived name (taken from DEST by default)') 30 | parser.add_argument('--has-bundle', action='store_true', help='set Finder flag indicating BNDL resource present') 31 | parser.add_argument('dest', metavar='DEST', help='HQX file') 32 | 33 | args = parser.parse_args() 34 | 35 | 36 | # make an auto filename 37 | if args.name: 38 | name = args.name 39 | else: 40 | name = os.path.basename(args.dest) 41 | 42 | base, ext = os.path.splitext(name) 43 | if ext.lower() == '.hqx': 44 | name = base 45 | 46 | assert name 47 | 48 | finfo = binhex.FInfo() 49 | finfo.Creator = args.creator 50 | finfo.Type = args.type 51 | finfo.Flags = 0x2000 if args.has_bundle else 0 52 | 53 | rsrc_fork, data_fork = (get_file(f) if f else b'' for f in [args.rsrc, args.data]) 54 | 55 | 56 | bh = binhex.BinHex((name, finfo, len(data_fork), len(rsrc_fork)), args.dest) 57 | 58 | bh.write(data_fork) 59 | bh.write_rsrc(rsrc_fork) 60 | 61 | bh.close() 62 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | tbxi tbxi.hqx: scripts/bootmake.py trampoline.elf parcels 2 | rm -f tbxi # in case of stray resource fork 3 | ./scripts/bootmake.py tbxi trampoline.elf parcels 4 | SetFile -t tbxi -c chrp tbxi || true # try to set finfo on macOS 5 | 6 | # cd ../enablifier && ./enablify templates/mac-os-rom-9.6.1 "$(CURDIR)/tbxi" # Uncomment to use https://github.com/elliotnunn/enablifier (requires macOS) 7 | 8 | rm -f rsrcfork && touch rsrcfork && cp tbxi/..namedfork/rsrc rsrcfork 2>/dev/null || true # try to preserve rsrc fork before binhexing 9 | scripts/binhexmake.py --data=tbxi --rsrc=rsrcfork --type=tbxi --creator=chrp --name="Mac OS ROM" tbxi.hqx 10 | rm -f rsrcfork 11 | 12 | # Tomfoolery required to be able to put prclmake.py args in another file 13 | parcels: scripts/prclmake.py scripts/prcltool.py parcel-layout.txt scripts/lzss rom $(shell find pef -type f -not -path '*/\.*') 14 | sh -c "scripts/prclmake.py $@ `sed 's/#.*//' parcel-layout.txt | tr '\n' ' '`" 15 | 16 | # Uncomment this block to use https://github.com/elliotnunn/powermac-rom 17 | # rom: phonyrom 18 | # .PHONY: phonyrom 19 | # phonyrom: 20 | # @echo "> Diving into powermac-rom repo" 21 | # @cd ../powermac-rom && ./EasyBuild.sh && cp BuildResults/PowerROM "$(CURDIR)/rom-new" 22 | # @cmp -s rom-new rom || mv rom-new rom 23 | # @rm -f rom-new 24 | # @echo "< Done with powermac-rom repo" 25 | 26 | scripts/lzss: lzss.c 27 | gcc -O2 -o $@ $< 28 | 29 | clean: 30 | rm -rf tbxi tbxi.hqx rsrcfork parcels scripts/lzss scripts/__pycache__ 31 | find . -type f -name '*.patch' -delete 32 | 33 | 34 | # For testing 35 | 36 | REMOTE_DISK_NAME = Alpha 37 | REMOTE_MACHINE = elliotnunn@Tigerbook.local 38 | 39 | test-qemu: tbxi.hqx 40 | $(HOME)/qemu/qemu-with-tbxi.sh $< 41 | 42 | test-fw: tbxi.hqx 43 | until mount | grep -q "/Volumes/$(REMOTE_DISK_NAME)"; do sleep 0.2; done \ 44 | # START THE TEST MACHINE IN TARGET DISK MODE 45 | rm -f "/Volumes/$(REMOTE_DISK_NAME)/System Folder/Mac OS ROM" 46 | binhex -o "/Volumes/$(REMOTE_DISK_NAME)/System Folder/Mac OS ROM" $< 47 | diskutil unmountDisk force /dev/`diskutil info /Volumes/$(REMOTE_DISK_NAME)/ | grep "Part of Whole" | sed 's/.*:\s*//'` 48 | tput bel && say "ROM copied." 49 | 50 | test-netfw: tbxi.hqx 51 | scp -q tbxi.hqx $(REMOTE_MACHINE):/tmp/tbxi.hqx 52 | ssh $(REMOTE_MACHINE) '\ 53 | until ls "/Volumes/$(REMOTE_DISK_NAME)/System Folder" >/dev/null 2>/dev/null; \ 54 | do sleep 0.15; \ 55 | done; \ 56 | rm -f "/Volumes/$(REMOTE_DISK_NAME)/System Folder/Mac OS ROM" && \ 57 | /usr/local/bin/unar -force-overwrite -output-directory "/Volumes/$(REMOTE_DISK_NAME)/System Folder" /tmp/tbxi.hqx && \ 58 | diskutil unmountDisk force "/Volumes/$(REMOTE_DISK_NAME)" \ 59 | ' # START THE TEST MACHINE IN TARGET DISK MODE 60 | tput bel && say "ROM copied." 61 | -------------------------------------------------------------------------------- /scripts/prclmake.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | from prcltool import ParcelsArea, ParcelStruct, ParcelEntry 4 | import argparse 5 | from sys import argv 6 | 7 | 8 | class DataLoader(argparse.Action): 9 | def __call__(self, parser, namespace, values, option_string=None): 10 | path = values[0] 11 | 12 | try: 13 | p2 = path + '.patch' 14 | with open(p2, 'rb') as f: 15 | namespace.bytes = f.read() 16 | print('Using', p2) 17 | except FileNotFoundError: 18 | with open(path, 'rb') as f: 19 | namespace.bytes = f.read() 20 | 21 | class DataReader(argparse.Action): 22 | def __call__(self, parser, namespace, values, option_string=None): 23 | d = b''.join(s.encode('ascii')+b'\0' for s in values) 24 | namespace.bytes = d 25 | namespace.should_checksum = False 26 | 27 | def hex(s): 28 | return int(s, 16) 29 | 30 | def fourcc(s): 31 | b = s.encode('ascii') 32 | if len(b) != 4: 33 | raise ValueError('type code not four bytes') 34 | return b 35 | 36 | p1 = argparse.ArgumentParser() 37 | p2 = argparse.ArgumentParser() 38 | 39 | p1.add_argument('--flags', '-f', action='store', type=hex, default=0) 40 | p1.add_argument('--fourcc', '-t', action='store', type=fourcc, default=' ') 41 | p1.add_argument('--name', '-n', action='store', default='') 42 | p1.add_argument('--compat', '-c', action='store', default='') 43 | 44 | p2.add_argument('--fourcc', '-t', action='store', type=fourcc, default=' ') 45 | p2.add_argument('--flags', '-f', action='store', type=hex, default=0) 46 | p2.add_argument('--lzss', '-l', action='store_true', dest='compress') 47 | p2.add_argument('--name', '-n', action='store', default='') 48 | p2.add_argument('--backref', action='store_true', dest='backref_allowed') 49 | p2.add_argument('--nosum', action='store_false', dest='should_checksum') 50 | p2.add_argument('--src', '-s', nargs=1, dest='bytes', action=DataLoader) 51 | p2.add_argument('--data', '-d', nargs='+', dest='bytes', action=DataReader) 52 | 53 | 54 | # Usage: prog.py [ --prcl prcl-opts [ --bin bin-opts ] ... ] ... 55 | 56 | progname, dest, *args = argv 57 | 58 | groups = [] 59 | 60 | me = ParcelsArea() 61 | 62 | for a in args: 63 | if a in ('--prcl', '--bin'): 64 | n = [] 65 | groups.append(n) 66 | n.append(a) 67 | 68 | for g in groups: 69 | t, *opts = g 70 | 71 | if t == '--prcl': 72 | prcl = ParcelStruct() 73 | p1.parse_args(args=opts, namespace=prcl) 74 | me.prcls.append(prcl) 75 | elif t == '--bin': 76 | bn = ParcelEntry() 77 | p2.parse_args(args=opts, namespace=bn) 78 | prcl.entries.append(bn) 79 | else: 80 | raise ValueError('bad arg') 81 | 82 | with open(dest, 'wb') as f: 83 | f.write(bytes(me)) 84 | -------------------------------------------------------------------------------- /parcel-layout.txt: -------------------------------------------------------------------------------- 1 | # These are arguments to prclmake.py, which get put through a hacky process in the Makefile. 2 | # Basically, from # to EOL gets deleted, and newlines become spaces. 3 | 4 | --prcl -f=00020000 -t=node -n="CodePrepare Node Parcel" -c= 5 | --bin -f=00000000 -t=cstr -n=name --data AAPL,CodePrepare 6 | --bin -f=00000000 -t=csta -n=AAPL,prepare_order --data Placeholder 7 | --bin -f=00020094 -t=nlib -n=TimeManagerLib -l --src=pef/nlib/TimeManagerLib 8 | --bin -f=00020094 -t=nlib -n=NVRAMServicesLib -l --src=pef/nlib/NVRAMServicesLib 9 | --bin -f=00020094 -t=nlib -n=RTCServicesLib -l --src=pef/nlib/RTCServicesLib 10 | 11 | --prcl -f=00010000 -t=node -n="CodeRegister Node Parcel" -c= 12 | --bin -f=00000000 -t=cstr -n=name --data AAPL,CodeRegister 13 | --bin -f=00010094 -t=nlib -n=NativePowerMgrLib -l --src=pef/nlib/NativePowerMgrLib 14 | --bin -f=00010094 -t=nlib -n=AGPLib -l --src=pef/nlib/AGPLib 15 | --bin -f=00010194 -t=nlib -n=EtherPrintfLib -l --src=pef/nlib/EtherPrintfLib 16 | --bin -f=00010094 -t=shlb -n=StartLib -l --src=pef/shlb/StartLib 17 | 18 | --prcl -f=00000000 -t="rom " -n="Mac OS ROM Parcel" -c= 19 | --bin -f=00000005 -t="rom " -n= -l --src=rom 20 | 21 | --prcl -f=00000000 -t=psum -n="Property Checksum" -c= 22 | --bin -f=00000000 -t=csta -n= --data 23 | name 24 | model 25 | compatible 26 | device_type 27 | reg 28 | assigned-addresses 29 | slot-names 30 | vendor-id 31 | device-id 32 | class-code 33 | devsel-speed 34 | fast-back-to-back 35 | bootpath 36 | mac-address 37 | --bin -f=00000000 -t=csta -n= --data 38 | boot-rom 39 | macos 40 | --bin -f=00000000 -t=csta -n= --data 41 | Placeholder 42 | --bin -f=00000000 -t=csta -n= --data 43 | Placeholder 44 | --bin -f=00000000 -t=csta -n= --data 45 | usb 46 | ieee1394 47 | 48 | --prcl -f=0000000c -t=prop -n=apple21143 -c=network 49 | --bin -f=00000006 -t=shlb -n=lanLib,AAPL,MacOS,PowerPC -l --src=pef/shlb/lanLib/apple21143 50 | 51 | --prcl -f=00000009 -t=prop -n=backlight -c=backlight 52 | --bin -f=00000000 -t=ndrv -n=driver,AAPL,MacOS,PowerPC --src=pef/ndrv/BacklightDriver --nosum 53 | --bin -f=00000002 -t=cstr -n=code,AAPL,MacOS,name --data BacklightDriver 54 | 55 | --prcl -f=0000000c -t=prop -n=bmac+ -c=network 56 | --bin -f=00000006 -t=shlb -n=lanLib,AAPL,MacOS,PowerPC -l --src=pef/shlb/lanLib/bmac+ 57 | 58 | --prcl -f=0000000c -t=prop -n=cmd646-ata -c=ata 59 | --bin -f=00000006 -t=ndrv -n=driver,AAPL,MacOS,PowerPC -l --src=pef/ndrv/ata/cmd646 60 | 61 | --prcl -f=00000008 -t=prop -n=cofb -c=display 62 | --bin -f=00000024 -t=ndrv -n=driver,AAPL,MacOS,PowerPC -l --src=pef/ndrv/display 63 | 64 | --prcl -f=0000000c -t=prop -n=cuda -c=via-cuda 65 | --bin -f=00000000 -t=ndrv -n=pef,AAPL,MacOS,PowerPC,register -l --src=pef/ndrv/PowerMgrPlugin/cuda --nosum 66 | --bin -f=00000002 -t=cstr -n=code,AAPL,MacOS,name --data PowerMgrPlugin 67 | 68 | --prcl -f=0000000c -t=prop -n=gmac -c=network 69 | --bin -f=00000006 -t=shlb -n=lanLib,AAPL,MacOS,PowerPC -l --src=pef/shlb/lanLib/gmac 70 | 71 | --prcl -f=0000000c -t=prop -n=grackle -c=pci 72 | --bin -f=00000016 -t=nlib -n=pef,AAPL,MacOS,PowerPC,prepare -l --src=pef/nlib/PCICyclesLib/Grackle 73 | --bin -f=00000000 -t=cstr -n=code,AAPL,MacOS,name --data Grackle_PCICyclesLib 74 | 75 | --prcl -f=0000000c -t=prop -n=heathrow-ata -c=ide 76 | --bin -f=00000006 -t=ndrv -n=driver,AAPL,MacOS,PowerPC -l --src=pef/ndrv/ata/heathrow 77 | 78 | --prcl -f=0000000c -t=prop -n=heathrow-ata -c=ata 79 | --bin -f=00000002 -t=ndrv -n=driver,AAPL,MacOS,PowerPC -l --src=pef/ndrv/ata/heathrow --backref 80 | 81 | --prcl -f=0000000c -t=prop -n=kauai-ata -c=ata 82 | --bin -f=00000006 -t=ndrv -n=driver,AAPL,MacOS,PowerPC -l --src=pef/ndrv/ata/kauai 83 | 84 | --prcl -f=0000000c -t=prop -n=keylargo-ata -c=ata 85 | --bin -f=00000006 -t=ndrv -n=driver,AAPL,MacOS,PowerPC -l --src=pef/ndrv/ata/keylargo 86 | 87 | --prcl -f=0000000c -t=prop -n=keywest-i2c -c=i2c 88 | --bin -f=00000006 -t=ndrv -n=driver,AAPL,MacOS,PowerPC -l --src=pef/ndrv/i2c 89 | 90 | --prcl -f=0000000a -t=prop -n=mac-io -c=nvram 91 | --bin -f=00000004 -t=ndrv -n=driver,AAPL,MacOS,PowerPC -l --src=pef/ndrv/nvram/mac-io 92 | 93 | --prcl -f=00000001 -t=prop -n=macos -c= 94 | --bin -f=00000000 -t=cstr -n=MacOSROMFile-version --data 9.6f1 95 | 96 | --prcl -f=0000000c -t=prop -n=nvram,flash -c=nvram 97 | --bin -f=00000004 -t=ndrv -n=driver,AAPL,MacOS,PowerPC -l --src=pef/ndrv/nvram/flash 98 | 99 | --prcl -f=0000000c -t=prop -n=pci104c,ac1a -c=cardbus 100 | --bin -f=00000016 -t=ndrv -n=driver,AAPL,MacOS,PowerPC -l --src=pef/ndrv/cardbus 101 | --bin -f=00010094 -t=nlib -n=PCCard -l --src=pef/nlib/PCCardLib 102 | 103 | --prcl -f=0000000c -t=prop -n=pci104c,ac50 -c=cardbus 104 | --bin -f=00000016 -t=ndrv -n=driver,AAPL,MacOS,PowerPC -l --src=pef/ndrv/cardbus --backref 105 | --bin -f=00010094 -t=nlib -n=PCCard -l --src=pef/nlib/PCCardLib 106 | 107 | --prcl -f=0000020c -t=prop -n=pciclass,0c0010 -c=ieee1394 108 | --bin -f=00000004 -t=ndrv -n=driver,AAPL,MacOS,PowerPC -l --src=pef/ndrv/firewire 109 | --bin -f=00010096 -t=nlib -n=FWServicesLib -l --src=pef/nlib/FWServicesLib 110 | --bin -f=00010096 -t=nlib -n=DevNLib -l --src=pef/nlib/DevNLib 111 | --bin -f=00010096 -t=nlib -n=DFMLib -l --src=pef/nlib/DFMLib 112 | --bin -f=00010096 -t=nlib -n=GenericDriverFamily -l --src=pef/nlib/GenericDriverFamily 113 | 114 | --prcl -f=0000000c -t=prop -n=pmu -c=power-mgt 115 | --bin -f=00000000 -t=ndrv -n=pef,AAPL,MacOS,PowerPC,register -l --src=pef/ndrv/PowerMgrPlugin/pmu --nosum 116 | --bin -f=00000002 -t=cstr -n=code,AAPL,MacOS,name --data PowerMgrPlugin --backref 117 | --bin -f=00000002 -t=cstr -n=target-mode-capable --data SCSI 118 | --bin -f=00010096 -t=nlib -n=PMULib -l --src=pef/nlib/PMULib 119 | 120 | --prcl -f=0000000c -t=prop -n=uni-n-i2c -c=i2c 121 | --bin -f=00000006 -t=ndrv -n=driver,AAPL,MacOS,PowerPC -l --src=pef/ndrv/i2c 122 | 123 | --prcl -f=0000000c -t=prop -n=uni-north -c=pci 124 | --bin -f=00000016 -t=nlib -n=pef,AAPL,MacOS,PowerPC,prepare -l --src=pef/nlib/PCICyclesLib/UniNorth 125 | --bin -f=00000002 -t=cstr -n=code,AAPL,MacOS,name --data UniNorth_PCICyclesLib 126 | 127 | --prcl -f=0000000a -t=prop -n=via-cuda -c=rtc 128 | --bin -f=00000004 -t=ndrv -n=driver,AAPL,MacOS,PowerPC -l --src=pef/ndrv/rtc/via-cuda 129 | 130 | --prcl -f=0000000a -t=prop -n=via-pmu -c=nvram 131 | --bin -f=00000004 -t=ndrv -n=driver,AAPL,MacOS,PowerPC -l --src=pef/ndrv/nvram/via-pmu 132 | 133 | --prcl -f=0000000a -t=prop -n=via-pmu -c=rtc 134 | --bin -f=00000004 -t=ndrv -n=driver,AAPL,MacOS,PowerPC -l --src=pef/ndrv/rtc/via-pmu 135 | 136 | --prcl -f=0000000c -t=prop -n=via-pmu-2000 -c=power-mgt 137 | --bin -f=00000000 -t=ndrv -n=pef,AAPL,MacOS,PowerPC,register -l --src=pef/ndrv/PowerMgrPlugin/pmu-2000 --nosum 138 | --bin -f=00000002 -t=cstr -n=code,AAPL,MacOS,name --data PowerMgrPlugin --backref 139 | --bin -f=00010096 -t=nlib -n=PMULib -l --src=pef/nlib/PMULib --backref 140 | 141 | --prcl -f=0000000c -t=prop -n=via-pmu-99 -c=power-mgt 142 | --bin -f=00000000 -t=ndrv -n=pef,AAPL,MacOS,PowerPC,register -l --src=pef/ndrv/PowerMgrPlugin/pmu-99 --nosum 143 | --bin -f=00000002 -t=cstr -n=code,AAPL,MacOS,name --data PowerMgrPlugin --backref 144 | --bin -f=00010096 -t=nlib -n=PMULib -l --src=pef/nlib/PMULib --backref 145 | -------------------------------------------------------------------------------- /scripts/prcltool.py: -------------------------------------------------------------------------------- 1 | # Ripped from somewhere else. 2 | # Can kind-of rip parcels. 3 | # Needs neatening up. 4 | 5 | import struct 6 | from binascii import crc32 7 | import lzss 8 | import struct 9 | 10 | class ParcelsArea: 11 | MAGIC = b'prcl \x01\x00\x00\x00 \x00\x00\x00\x14 \x00\x00\x00\x14 \x00\x00\x00\x00'.replace(b' ', b'') 12 | 13 | def __init__(self, bytes=None): 14 | if bytes is not None: 15 | if not bytes.startswith(self.MAGIC): 16 | raise ValueError('Instead of a prcl magic number: %r' % bytes[:len(self.MAGIC)]) 17 | 18 | # Read all the structs in the prcl area! 19 | prcls = ParcelStruct.scan(bytes=bytes, first_offset=len(self.MAGIC)) 20 | prcls = list(prcls) 21 | self.prcls = prcls 22 | 23 | for prcl in prcls: 24 | for entry in prcl.entries: 25 | tpl = (entry.load_offset, entry.load_len, entry.compress) 26 | 27 | x = bytes[entry.load_offset : entry.load_offset+entry.load_len] 28 | if entry.compress: 29 | x = lzss.extract(x) 30 | entry.bytes = x 31 | 32 | else: 33 | self.prcls = [] 34 | 35 | def __bytes__(self): 36 | binaries_added = {} # (bytes, compress): (compressed_bytes, offset, cksum) 37 | things = bytearray(self.MAGIC) 38 | 39 | for prcl in self.prcls: 40 | prcl_offset = len(things) 41 | things.extend(bytes(len(prcl))) 42 | 43 | for entry in prcl.entries: 44 | dict_lookup = (entry.bytes, entry.compress) 45 | 46 | try: 47 | if not entry.backref_allowed: raise ValueError 48 | final_bytes, bytes_offset, cksum = binaries_added[dict_lookup] 49 | 50 | except: 51 | # Need to use this binary! 52 | final_bytes = entry.bytes 53 | if entry.compress: 54 | final_bytes = lzss.compress(final_bytes) 55 | 56 | bytes_offset = len(things) 57 | cksum = crc32(final_bytes) 58 | 59 | things.extend(final_bytes) 60 | 61 | binaries_added[dict_lookup] = final_bytes, bytes_offset, cksum 62 | 63 | # Pad to 4-byte boundary. Apple's build tool left pad bytes uninitialised! 64 | while len(things) % 4: 65 | things.append(0x99) 66 | 67 | # Tell this structure where it can find its binary data. 68 | entry.uncompressed_len = len(entry.bytes) 69 | entry.save_cksum = cksum if entry.should_checksum else 0 70 | entry.save_offset = bytes_offset 71 | entry.save_len = len(final_bytes) 72 | 73 | # Then tell it where it can find the next one, if any 74 | if prcl is self.prcls[-1]: 75 | prcl.save_nextoffset = 0 76 | else: 77 | prcl.save_nextoffset = len(things) 78 | 79 | things[prcl_offset:prcl_offset+len(prcl)] = bytes(prcl) 80 | 81 | # So now all structs and all data are placed. Phew. 82 | return bytes(things) 83 | 84 | 85 | class ParcelStruct: 86 | HEADER_FMT = '>I4s4I32s32s' 87 | 88 | @classmethod 89 | def scan(cls, bytes, first_offset): 90 | offset = first_offset 91 | 92 | while offset: 93 | parcel = cls(bytes=bytes, offset=offset) 94 | yield parcel 95 | offset = parcel.load_nextoffset 96 | 97 | def __init__(self, bytes=None, offset=None): 98 | if bytes is not None: 99 | load_nextoffset, fourcc, my_len, flags, entry_count, entry_len, name, compat = struct.unpack_from(self.HEADER_FMT, bytes, offset) 100 | 101 | # Checks 102 | # if entry_len != ParcelEntry.__len__(): 103 | # raise ValueError('Parcel entry of %d bytes, expected %d' % (entry_len, ParcelEntry.__len__())) 104 | 105 | # if my_len != header_size + entry_count*entry_len: 106 | # raise ValueError('Incorrect parcel header size field %d not %d' % (my_len, struct.calcsize(self.HEADER_FMT) + entry_count*entry_len)) 107 | 108 | # Semantics 109 | self.fourcc = fourcc 110 | self.name = name.rstrip(b'\0').decode('ascii') 111 | self.compat = compat.rstrip(b'\0').decode('ascii') 112 | self.flags = flags 113 | 114 | len_of_entries = entry_count*entry_len 115 | entry_offsets = range(offset + my_len - len_of_entries, offset + my_len, entry_len) 116 | self.entries = [ParcelEntry(bytes[o : o+entry_len]) for o in entry_offsets] 117 | 118 | # Ephemerides 119 | self.load_nextoffset = load_nextoffset 120 | 121 | else: 122 | self.fourcc = b' ' 123 | self.name = '' 124 | self.compat = '' 125 | self.flags = 0 126 | 127 | self.entries = [] 128 | 129 | def __len__(self): 130 | return struct.calcsize(self.HEADER_FMT) + sum(len(e) for e in self.entries) 131 | 132 | def __bytes__(self): 133 | save_nextoffset = self.save_nextoffset 134 | fourcc = self.fourcc 135 | my_len = len(self) 136 | flags = self.flags 137 | entry_count = len(self.entries) 138 | entry_len = ParcelEntry.__len__() 139 | name = self.name.encode('ascii') 140 | compat = self.compat.encode('ascii') 141 | 142 | header = struct.pack(self.HEADER_FMT, save_nextoffset, fourcc, my_len, flags, entry_count, entry_len, name, compat) 143 | 144 | entries = b''.join(bytes(e) for e in self.entries) 145 | 146 | return header + entries 147 | 148 | class ParcelEntry: 149 | FMT = '>4sI4s4I32s' 150 | 151 | def __init__(self, bytes=None): 152 | if bytes is not None: 153 | (fourcc, flags, compress, uncompressed_len, load_cksum, load_len, load_offset, name) = struct.unpack(self.FMT, bytes) 154 | 155 | self.fourcc = fourcc 156 | self.flags = flags 157 | self.compress = (compress == b'lzss') 158 | self.uncompressed_len = uncompressed_len 159 | self.name = name.rstrip(b'\0').decode('ascii') 160 | self.backref_allowed = False 161 | self.should_checksum = True 162 | 163 | # Ephemeral stuff 164 | self.load_cksum = load_cksum 165 | self.load_len = load_len 166 | self.load_offset = load_offset 167 | 168 | #else: 169 | # self.fourcc = b' ' 170 | # self.flags = 0 171 | # self.compress = False 172 | # self.uncompressed_len = 0 173 | # self.name = '' 174 | 175 | def __bytes__(self): 176 | fourcc = self.fourcc 177 | flags = self.flags 178 | compress = b'lzss' if self.compress else b'\0\0\0\0' 179 | uncompressed_len = self.uncompressed_len 180 | save_cksum = self.save_cksum 181 | save_len = self.save_len 182 | save_offset = self.save_offset 183 | name = self.name.encode('ascii') 184 | 185 | return struct.pack(self.FMT, fourcc, flags, compress, uncompressed_len, save_cksum, save_len, save_offset, name) 186 | 187 | @classmethod 188 | def __len__(cls): 189 | return struct.calcsize(cls.FMT) 190 | -------------------------------------------------------------------------------- /lzss.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #define circ(buffer, offset) ((buffer)[(offset) % sizeof(buffer)]) 6 | 7 | 8 | const int lookup_size = 2; 9 | const int thresh_n = 3; 10 | const int max_n = 18; // Four bits of lookup 11 | 12 | 13 | 14 | 15 | 16 | /************************************************************** 17 | LZSS.C -- A Data Compression Program 18 | *************************************************************** 19 | 4/6/1989 Haruhiko Okumura 20 | Use, distribute, and modify this program freely. 21 | Please send me your improved versions. 22 | PC-VAN SCIENCE 23 | NIFTY-Serve PAF01022 24 | CompuServe 74050,1022 25 | **************************************************************/ 26 | 27 | #define N 4096 /* size of ring buffer - must be power of 2 */ 28 | #define F 18 /* upper limit for match_length */ 29 | #define THRESHOLD 2 /* encode string into position and length 30 | if match_length is greater than this */ 31 | #define NIL N /* index for root of binary search trees */ 32 | 33 | struct encode_state { 34 | /* 35 | * left & right children & parent. These constitute binary search trees. 36 | */ 37 | int lchild[N + 1], rchild[N + 257], parent[N + 1]; 38 | 39 | /* ring buffer of size N, with extra F-1 bytes to aid string comparison */ 40 | uint8_t text_buf[N + F - 1]; 41 | 42 | /* 43 | * match_length of longest match. 44 | * These are set by the insert_node() procedure. 45 | */ 46 | int match_position, match_length; 47 | }; 48 | 49 | 50 | int 51 | decompress_lzss(uint8_t *dst, uint8_t *src, uint32_t srclen) 52 | { 53 | /* ring buffer of size N, with extra F-1 bytes to aid string comparison */ 54 | uint8_t text_buf[N + F - 1]; 55 | uint8_t *dststart = dst; 56 | uint8_t *srcend = src + srclen; 57 | int i, j, k, r, c; 58 | unsigned int flags; 59 | 60 | dst = dststart; 61 | srcend = src + srclen; 62 | for (i = 0; i < N - F; i++) 63 | text_buf[i] = ' '; 64 | r = N - F; 65 | flags = 0; 66 | for ( ; ; ) { 67 | if (((flags >>= 1) & 0x100) == 0) { 68 | if (src < srcend) c = *src++; else break; 69 | flags = c | 0xFF00; /* uses higher byte cleverly */ 70 | } /* to count eight */ 71 | if (flags & 1) { 72 | if (src < srcend) c = *src++; else break; 73 | *dst++ = c; 74 | text_buf[r++] = c; 75 | r &= (N - 1); 76 | } else { 77 | if (src < srcend) i = *src++; else break; 78 | if (src < srcend) j = *src++; else break; 79 | i |= ((j & 0xF0) << 4); 80 | j = (j & 0x0F) + THRESHOLD; 81 | for (k = 0; k <= j; k++) { 82 | c = text_buf[(i + k) & (N - 1)]; 83 | *dst++ = c; 84 | text_buf[r++] = c; 85 | r &= (N - 1); 86 | } 87 | } 88 | } 89 | 90 | return dst - dststart; 91 | } 92 | 93 | /* 94 | * initialize state, mostly the trees 95 | * 96 | * For i = 0 to N - 1, rchild[i] and lchild[i] will be the right and left 97 | * children of node i. These nodes need not be initialized. Also, parent[i] 98 | * is the parent of node i. These are initialized to NIL (= N), which stands 99 | * for 'not used.' For i = 0 to 255, rchild[N + i + 1] is the root of the 100 | * tree for strings that begin with character i. These are initialized to NIL. 101 | * Note there are 256 trees. */ 102 | static void init_state(struct encode_state *sp) 103 | { 104 | int i; 105 | 106 | memset(sp, 0, sizeof(*sp)); 107 | 108 | for (i = 0; i < N - F; i++) 109 | sp->text_buf[i] = ' '; 110 | for (i = N + 1; i <= N + 256; i++) 111 | sp->rchild[i] = NIL; 112 | for (i = 0; i < N; i++) 113 | sp->parent[i] = NIL; 114 | } 115 | 116 | /* 117 | * Inserts string of length F, text_buf[r..r+F-1], into one of the trees 118 | * (text_buf[r]'th tree) and returns the longest-match position and length 119 | * via the global variables match_position and match_length. 120 | * If match_length = F, then removes the old node in favor of the new one, 121 | * because the old one will be deleted sooner. Note r plays double role, 122 | * as tree node and position in buffer. 123 | */ 124 | static void insert_node(struct encode_state *sp, int r) 125 | { 126 | int i, p, cmp; 127 | uint8_t *key; 128 | 129 | cmp = 1; 130 | key = &sp->text_buf[r]; 131 | p = N + 1 + key[0]; 132 | sp->rchild[r] = sp->lchild[r] = NIL; 133 | sp->match_length = 0; 134 | for ( ; ; ) { 135 | if (cmp >= 0) { 136 | if (sp->rchild[p] != NIL) 137 | p = sp->rchild[p]; 138 | else { 139 | sp->rchild[p] = r; 140 | sp->parent[r] = p; 141 | return; 142 | } 143 | } else { 144 | if (sp->lchild[p] != NIL) 145 | p = sp->lchild[p]; 146 | else { 147 | sp->lchild[p] = r; 148 | sp->parent[r] = p; 149 | return; 150 | } 151 | } 152 | for (i = 1; i < F; i++) { 153 | if ((cmp = key[i] - sp->text_buf[p + i]) != 0) 154 | break; 155 | } 156 | if (i > sp->match_length) { 157 | sp->match_position = p; 158 | if ((sp->match_length = i) >= F) 159 | break; 160 | } 161 | } 162 | sp->parent[r] = sp->parent[p]; 163 | sp->lchild[r] = sp->lchild[p]; 164 | sp->rchild[r] = sp->rchild[p]; 165 | sp->parent[sp->lchild[p]] = r; 166 | sp->parent[sp->rchild[p]] = r; 167 | if (sp->rchild[sp->parent[p]] == p) 168 | sp->rchild[sp->parent[p]] = r; 169 | else 170 | sp->lchild[sp->parent[p]] = r; 171 | sp->parent[p] = NIL; /* remove p */ 172 | } 173 | 174 | /* deletes node p from tree */ 175 | static void delete_node(struct encode_state *sp, int p) 176 | { 177 | int q; 178 | 179 | if (sp->parent[p] == NIL) 180 | return; /* not in tree */ 181 | if (sp->rchild[p] == NIL) 182 | q = sp->lchild[p]; 183 | else if (sp->lchild[p] == NIL) 184 | q = sp->rchild[p]; 185 | else { 186 | q = sp->lchild[p]; 187 | if (sp->rchild[q] != NIL) { 188 | do { 189 | q = sp->rchild[q]; 190 | } while (sp->rchild[q] != NIL); 191 | sp->rchild[sp->parent[q]] = sp->lchild[q]; 192 | sp->parent[sp->lchild[q]] = sp->parent[q]; 193 | sp->lchild[q] = sp->lchild[p]; 194 | sp->parent[sp->lchild[p]] = q; 195 | } 196 | sp->rchild[q] = sp->rchild[p]; 197 | sp->parent[sp->rchild[p]] = q; 198 | } 199 | sp->parent[q] = sp->parent[p]; 200 | if (sp->rchild[sp->parent[p]] == p) 201 | sp->rchild[sp->parent[p]] = q; 202 | else 203 | sp->lchild[sp->parent[p]] = q; 204 | sp->parent[p] = NIL; 205 | } 206 | 207 | uint8_t * 208 | compress_lzss(uint8_t *dst, uint32_t dstlen, uint8_t *src, uint32_t srcLen) 209 | { 210 | /* Encoding state, mostly tree but some current match stuff */ 211 | struct encode_state *sp; 212 | 213 | int i, c, len, r, s, last_match_length, code_buf_ptr; 214 | uint8_t code_buf[17], mask; 215 | uint8_t *srcend = src + srcLen; 216 | uint8_t *dstend = dst + dstlen; 217 | 218 | /* initialize trees */ 219 | sp = (struct encode_state *) malloc(sizeof(*sp)); 220 | init_state(sp); 221 | 222 | /* 223 | * code_buf[1..16] saves eight units of code, and code_buf[0] works 224 | * as eight flags, "1" representing that the unit is an unencoded 225 | * letter (1 byte), "" a position-and-length pair (2 bytes). 226 | * Thus, eight units require at most 16 bytes of code. 227 | */ 228 | code_buf[0] = 0; 229 | code_buf_ptr = mask = 1; 230 | 231 | /* Clear the buffer with any character that will appear often. */ 232 | s = 0; r = N - F; 233 | 234 | /* Read F bytes into the last F bytes of the buffer */ 235 | for (len = 0; len < F && src < srcend; len++) 236 | sp->text_buf[r + len] = *src++; 237 | if (!len) { 238 | free(sp); 239 | return (void *) 0; /* text of size zero */ 240 | } 241 | /* 242 | * Insert the F strings, each of which begins with one or more 243 | * 'space' characters. Note the order in which these strings are 244 | * inserted. This way, degenerate trees will be less likely to occur. 245 | */ 246 | for (i = 1; i <= F; i++) 247 | insert_node(sp, r - i); 248 | 249 | /* 250 | * Finally, insert the whole string just read. 251 | * The global variables match_length and match_position are set. 252 | */ 253 | insert_node(sp, r); 254 | do { 255 | /* match_length may be spuriously long near the end of text. */ 256 | if (sp->match_length > len) 257 | sp->match_length = len; 258 | if (sp->match_length <= THRESHOLD) { 259 | sp->match_length = 1; /* Not long enough match. Send one byte. */ 260 | code_buf[0] |= mask; /* 'send one byte' flag */ 261 | code_buf[code_buf_ptr++] = sp->text_buf[r]; /* Send uncoded. */ 262 | } else { 263 | /* Send position and length pair. Note match_length > THRESHOLD. */ 264 | code_buf[code_buf_ptr++] = (uint8_t) sp->match_position; 265 | code_buf[code_buf_ptr++] = (uint8_t) 266 | ( ((sp->match_position >> 4) & 0xF0) 267 | | (sp->match_length - (THRESHOLD + 1)) ); 268 | } 269 | if ((mask <<= 1) == 0) { /* Shift mask left one bit. */ 270 | /* Send at most 8 units of code together */ 271 | for (i = 0; i < code_buf_ptr; i++) 272 | if (dst < dstend) 273 | *dst++ = code_buf[i]; 274 | else { 275 | free(sp); 276 | return (void *) 0; 277 | } 278 | code_buf[0] = 0; 279 | code_buf_ptr = mask = 1; 280 | } 281 | last_match_length = sp->match_length; 282 | for (i = 0; i < last_match_length && src < srcend; i++) { 283 | delete_node(sp, s); /* Delete old strings and */ 284 | c = *src++; 285 | sp->text_buf[s] = c; /* read new bytes */ 286 | 287 | /* 288 | * If the position is near the end of buffer, extend the buffer 289 | * to make string comparison easier. 290 | */ 291 | if (s < F - 1) 292 | sp->text_buf[s + N] = c; 293 | 294 | /* Since this is a ring buffer, increment the position modulo N. */ 295 | s = (s + 1) & (N - 1); 296 | r = (r + 1) & (N - 1); 297 | 298 | /* Register the string in text_buf[r..r+F-1] */ 299 | insert_node(sp, r); 300 | } 301 | while (i++ < last_match_length) { 302 | delete_node(sp, s); 303 | 304 | /* After the end of text, no need to read, */ 305 | s = (s + 1) & (N - 1); 306 | r = (r + 1) & (N - 1); 307 | /* but buffer may not be empty. */ 308 | if (--len) 309 | insert_node(sp, r); 310 | } 311 | } while (len > 0); /* until length of string to be processed is zero */ 312 | 313 | if (code_buf_ptr > 1) { /* Send remaining code. */ 314 | for (i = 0; i < code_buf_ptr; i++) 315 | if (dst < dstend) 316 | *dst++ = code_buf[i]; 317 | else { 318 | free(sp); 319 | return (void *) 0; 320 | } 321 | } 322 | 323 | free(sp); 324 | return dst; 325 | } 326 | 327 | 328 | 329 | 330 | 331 | /* my nasty stuff */ 332 | 333 | // Yes, I know it's a mess. Feel free to clean it up, 334 | // but please don't change the command-line interface. 335 | int main(int argc, char *argv[]) 336 | { 337 | freopen(NULL, "rb", stdin); 338 | freopen(NULL, "wb", stderr); 339 | 340 | unsigned char dict[0x1000]; 341 | unsigned int dict_i = 0xFEE; 342 | 343 | if(argc == 2 && strcmp(argv[1], "x") == 0) 344 | { 345 | int head_char, lit, offset, len; 346 | 347 | while(1) 348 | { 349 | head_char = getchar(); 350 | if(head_char == EOF) return 0; 351 | 352 | head_char |= 0xFF00; //neat little hack, this 353 | 354 | while(head_char != 0xFF) 355 | { 356 | if(head_char & 1) 357 | { // Literal read (1 char) 358 | lit = getchar(); 359 | if(lit == EOF) return 0; 360 | 361 | circ(dict, dict_i++) = lit; 362 | putchar(lit); 363 | } 364 | else 365 | { // Dictionary read (2 bytes, offset and thingo) 366 | offset = getchar(); 367 | len = getchar(); 368 | if(offset == EOF) return 0; 369 | 370 | offset |= (len & 0xF0) << 4; 371 | len &= 0x0F; 372 | len += 3; 373 | 374 | for(int i=0; i>= 1; 382 | } 383 | } 384 | } 385 | else if(argc == 2 && strcmp(argv[1], "c") == 0) 386 | { 387 | uint8_t *a, *b, *ret; 388 | uint32_t alen; 389 | 390 | a = malloc(0x400000); 391 | b = malloc(0x400000); 392 | if(!a || !b) return 1; 393 | 394 | alen = fread(a, 1, 0x400000, stdin); 395 | 396 | ret = compress_lzss(b, 0x400000, a, alen); 397 | if(!ret) return 1; 398 | 399 | if(fwrite(b, ret-b, 1, stdout) != 1) return 1; 400 | if(fclose(stdout)) return 1; 401 | 402 | return 0; 403 | } 404 | else 405 | { 406 | fprintf(stderr, "USAGE: lzss [x|c]\n"); 407 | return 1; 408 | } 409 | } 410 | 411 | #define BUF_SIZE 512 412 | #define BUF_MIN 128 413 | -------------------------------------------------------------------------------- /scripts/bootmake.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | from zlib import adler32 4 | from sys import argv 5 | from html import escape as html_escape 6 | import re 7 | 8 | def html_escape_forth(f): 9 | return re.sub(r'[<>]+', lambda m: html_escape(m.group()), f) 10 | 11 | 12 | 13 | # Set constants. 14 | 15 | # The COMPATIBLE field at the top of the script 16 | COMPATIBLE = [ 17 | "MacRISC", 18 | # "MacRISC2", 19 | # "MacRISC3", 20 | # "MacRISC4", 21 | ] 22 | 23 | # Changes to the Forth boot script, all off by default 24 | DELETE_MODEL_CHECK = False 25 | DELETE_CHECKSUM_CHECK = False 26 | G4_FIX = False 27 | 28 | # *After* OF has loaded this file, set the "model" property? 29 | SET_MODEL_PROPERTY = '' 30 | # SET_MODEL_PROPERTY = 'PowerMac5,1' # Cube 31 | 32 | # ...and the "compatible" property? (empty strings not counted) 33 | SET_COMPATIBLE_PROPERTY = [x for x in [ 34 | # SET_MODEL_PROPERTY, 35 | # *COMPATIBLE, 36 | # 'Power Macintosh', 37 | ] if x] 38 | 39 | SET_PRIM_INFO = None 40 | # SET_PRIM_INFO = ['000000ff', '0000002c', '00030d40', '0001e705', '00001400', '00000000', '0000260d', '46000270'] # for mini 41 | 42 | # Adds code to set the AAPL,debug property early in the boot script 43 | DEBUG_PROPERTY = 0 44 | # DEBUG_PROPERTY |= 0x00000001 # Print general informative messages. 45 | # DEBUG_PROPERTY |= 0x00000002 # Print formatted Mac OS tables (except config/universal info). 46 | # DEBUG_PROPERTY |= 0x00000004 # Print formatted config info table. 47 | # DEBUG_PROPERTY |= 0x00000008 # Dump Mac OS tables (except config/universal info). 48 | # DEBUG_PROPERTY |= 0x00000010 # Print node names while copying the device tree. 49 | # DEBUG_PROPERTY |= 0x00000020 # Print property info while copying the device tree. 50 | # DEBUG_PROPERTY |= 0x00000040 # Print interrupt-related info. 51 | # DEBUG_PROPERTY |= 0x00000080 # Print interrupt tree traversal info. 52 | # DEBUG_PROPERTY |= 0x00000100 # Print address resolution info. 53 | # DEBUG_PROPERTY |= 0x00000200 # Print NV-RAM info. 54 | # DEBUG_PROPERTY |= 0x00000400 # Print Mac OS "universal" info. 55 | # DEBUG_PROPERTY |= 0x00000800 # Print "special" node info. 56 | # DEBUG_PROPERTY |= 0x00001000 # Load EtherPrintf utility via parcel for post FCode debugging. 57 | # DEBUG_PROPERTY |= 0x00002000 # Print BOOTP/DHCP/BSDP information. 58 | # DEBUG_PROPERTY |= 0x00004000 # Allocate writable ROM aperture. 59 | # DEBUG_PROPERTY |= 0x00008000 # Mark Toolbox image as non-cacheable. 60 | # DEBUG_PROPERTY |= 0x00010000 # Print parcel info while copying the device tree. 61 | # DEBUG_PROPERTY |= 0x00020000 # Print information on device tree data checksums. 62 | # DEBUG_PROPERTY |= 0x01000000 # Enable the Nanokernel debugger. 63 | # DEBUG_PROPERTY |= 0x02000000 # Display the Nanokernel log during boot. 64 | # DEBUG_PROPERTY |= 0x10000000 # Dont attempt to unhibernate system. 65 | # DEBUG_PROPERTY |= 0x40000000 # Halt after end of FCode (useful if outputting to screen). 66 | 67 | # The OF-friendly parts of the file are padded out to 20k with nulls 68 | DATA_OFFSET = 0x5000 69 | 70 | 71 | 72 | # Load the two binary blobs, and save their offsets and sizes. 73 | 74 | out_path, elf_path, payload_path = argv[1:] 75 | 76 | 77 | tbxi = bytearray(DATA_OFFSET) 78 | 79 | for x in ['elf', 'payload']: 80 | locals()[x + '_offset'] = len(tbxi) 81 | with open(locals()[x + '_path'], 'rb') as f: 82 | data = f.read() 83 | while len(data) % 4: 84 | data.extend(b'\x00') 85 | locals()[x + '_size'] = len(data) 86 | locals()[x + '_data'] = data 87 | 88 | tbxi.extend(data) 89 | 90 | info_size = len(tbxi) 91 | 92 | 93 | 94 | # Put the payload in the correct device tree property. 95 | 96 | if b'AAPL,toolbox-parcels' in elf_data: 97 | # Used by v8-10 booters 98 | payload_type = 'parcels' 99 | payload_prop_name = 'AAPL,toolbox-parcels' 100 | else: 101 | # Used by v1 LZSSed-ROM-image booters, and by v3-7 parcels-based booters 102 | payload_type = 'lzss' 103 | payload_prop_name = 'AAPL,toolbox-image,lzss' 104 | 105 | 106 | 107 | # Assemble the CHRP-BOOT text for Open Firmware to parse. 108 | 109 | BOOT_SCRIPT = '' 110 | 111 | if SET_PRIM_INFO: 112 | BOOT_SCRIPT += "\ SET_PRIM_INFO\n" 113 | BOOT_SCRIPT += "dev via-pmu dev power-mgt\n" 114 | BOOT_SCRIPT += '%s encode-int\n' % SET_PRIM_INFO[0] 115 | for x in SET_PRIM_INFO[1:]: 116 | BOOT_SCRIPT += '%s encode-int encode+\n' % x 117 | BOOT_SCRIPT += '" prim-info" property\n' 118 | BOOT_SCRIPT += 'device-end\n' 119 | BOOT_SCRIPT += '\ END SET_PRIM_INFO\n' 120 | 121 | if DEBUG_PROPERTY: BOOT_SCRIPT += """ 122 | \ DEBUG_PROPERTY 123 | dev / 124 | %X encode-int " AAPL,debug" property 125 | device-end 126 | \ END DEBUG_PROPERTY 127 | """ % DEBUG_PROPERTY 128 | 129 | if SET_MODEL_PROPERTY: BOOT_SCRIPT += """ 130 | \ SET_MODEL_PROPERTY 131 | dev / 132 | " %s" encode-string " model" property 133 | device-end 134 | \ END SET_MODEL_PROPERTY 135 | """ % SET_MODEL_PROPERTY 136 | 137 | if SET_COMPATIBLE_PROPERTY: 138 | BOOT_SCRIPT += "\ SET_COMPATIBLE_PROPERTY\n" 139 | BOOT_SCRIPT += "dev /\n" 140 | BOOT_SCRIPT += '" %s" encode-string' % SET_COMPATIBLE_PROPERTY[0] 141 | for x in SET_COMPATIBLE_PROPERTY[1:]: 142 | BOOT_SCRIPT += ' " %s" encode-string encode+' % x 143 | BOOT_SCRIPT += ' " compatible" property\n' 144 | BOOT_SCRIPT += 'device-end\n' 145 | BOOT_SCRIPT += '\ END SET_COMPATIBLE_PROPERTY\n' 146 | 147 | if G4_FIX: BOOT_SCRIPT += """ 148 | \ G4_FIX: 149 | " /cpus/PowerPC,G4@0" find-package if 150 | " /cpus/PowerPC,G4@0" select-dev 151 | " cpu-version" active-package get-package-property 0= if 152 | decode-int 153 | 2swap 154 | 2drop 155 | 80010201 < 156 | 0= if 157 | 80010201 encode-int " cpu-version" property 158 | then 159 | then 160 | device-end 161 | then 162 | \ END G4_FIX 163 | """ 164 | 165 | BOOT_SCRIPT += """ 166 | here >r 167 | dev / 168 | """ 169 | 170 | if DELETE_MODEL_CHECK: BOOT_SCRIPT += """ 171 | \ Model check deleted 172 | """ 173 | else: BOOT_SCRIPT += """ 174 | " model" active-package get-package-property abort" can't find MODEL" 175 | decode-string 2swap 2drop " iMac,1" $= ?dup 0= if 176 | " compatible" active-package get-package-property abort" can't find COMPATIBLE" 177 | false >r 178 | begin 179 | dup while 180 | decode-string here over 2swap bounds ?do 181 | i c@ dup [char] A [char] Z between if h# 20 xor then c, 182 | loop 183 | %s 184 | 2drop 185 | repeat 186 | 2drop r> 187 | then 188 | r> here - allot 189 | 0= abort" this image is not for this platform" 190 | """ % '\n'.join(' 2dup " %s" $= r> or >r' % m.lower() for m in COMPATIBLE) 191 | 192 | if DELETE_CHECKSUM_CHECK: BOOT_SCRIPT += """ 193 | \ Checksum check deleted 194 | """ 195 | else: BOOT_SCRIPT += """ 196 | decimal 197 | 1 load-base load-size 14 - adler32 load-base load-size + 12 - 12 ['] eval catch if 198 | 2drop ." , bad checksum value" -1 199 | then 200 | <> if 201 | ." , checksum error" 202 | abort 203 | then 204 | hex 205 | """ 206 | 207 | BOOT_SCRIPT += """ 208 | dev /openprom 209 | 0 0 " supports-bootinfo" property device-end 210 | 211 | " /chosen" find-package 0= abort" can't find '/chosen'" constant /chosen 212 | " memory" /chosen get-package-property abort" memory??" decode-int constant xmem 2drop 213 | " mmu" /chosen get-package-property abort" mmu??" decode-int constant xmmu 2drop 214 | " AAPL,debug" " /" find-package 0= abort" can't find '/'" get-package-property if 215 | false 216 | else 217 | 2drop true 218 | then 219 | constant debug? 220 | debug? if cr ." checking for RELEASE-LOAD-AREA" then 221 | " release-load-area" $find 0= if 2drop false then constant 'release-load-area 222 | debug? if 'release-load-area if ." , found it" else ." , not found" then then 223 | : do-translate " translate" xmmu $call-method ; 224 | : do-map " map" xmmu $call-method ; 225 | : do-unmap " unmap" xmmu $call-method ; 226 | : claim-mem " claim" xmem $call-method ; 227 | : release-mem " release" xmem $call-method ; 228 | : claim-virt " claim" xmmu $call-method ; 229 | : release-virt " release" xmmu $call-method ; 230 | 1000 constant pagesz 231 | pagesz 1- constant pagesz-1 232 | -1000 constant pagemask 233 | h# {elf_offset:06X} constant elf-offset 234 | h# {elf_size:06X} constant elf-size 235 | elf-size pagesz-1 + pagemask and constant elf-pages 236 | h# {payload_offset:06X} constant {payload_type}-offset 237 | h# {payload_size:06X} constant {payload_type}-size 238 | {payload_type}-size pagesz-1 + pagemask and constant {payload_type}-pages 239 | h# {info_size:06X} constant info-size 240 | info-size pagesz-1 + pagemask and constant info-pages 241 | 0 value load-base-claim 242 | 0 value info-base 243 | 'release-load-area if 244 | load-base to info-base 245 | else 246 | load-base info-pages 0 ['] claim-mem catch if 3drop 0 then to load-base-claim 247 | info-pages 1000 claim-virt to info-base 248 | load-base info-base info-pages 10 do-map then 249 | \ allocate room for both images 250 | {payload_type}-pages 400000 claim-mem constant rom-phys {payload_type}-pages 1000 claim-virt constant rom-virt rom-phys rom-virt {payload_type}-pages 10 do-map 251 | elf-pages 1000 claim-mem constant elf-phys elf-pages 1000 claim-virt constant elf-virt 252 | elf-phys elf-virt elf-pages 10 do-map info-base elf-offset + elf-virt elf-size move debug? if cr ." elf-phys,elf-virt,elf-pages: " elf-phys u. ." , " elf-virt u. ." , " elf-pages u. then 253 | \ copy the compressed image 254 | debug? if cr ." copying compressed ROM image" then 255 | rom-virt {payload_type}-pages 0 fill 256 | info-base {payload_type}-offset + rom-virt {payload_type}-size move 257 | 'release-load-area 0= if 258 | info-base info-pages do-unmap load-base-claim ?dup if info-pages release-mem then 259 | then 260 | debug? if cr ." MacOS-ROM phys,virt,size: " rom-phys u. ." , " rom-virt u. ." , " {payload_type}-size u. then 261 | \ create the actual property 262 | debug? if cr ." finding/creating '/rom/macos' package" then 263 | device-end 0 to my-self 264 | " /rom" find-device 265 | " macos" ['] find-device catch if 2drop new-device " macos" device-name finish-device then 266 | " /rom/macos" find-device 267 | debug? if cr ." creating '{payload_prop_name}' property" then 268 | rom-virt encode-int {payload_type}-size encode-int encode+ " {payload_prop_name}" property 269 | device-end 270 | debug? if cr ." copying MacOS.elf to load-base" then 271 | 'release-load-area if 272 | load-base elf-pages + 'release-load-area execute 273 | else 274 | load-base elf-pages 0 claim-mem 275 | load-base dup elf-pages 0 do-map then 276 | elf-virt load-base elf-size move 277 | elf-virt elf-pages do-unmap elf-virt elf-pages release-virt 278 | elf-phys elf-pages release-mem 279 | debug? if cr ." init-program" then 280 | init-program 281 | debug? if cr ." .registers" .registers then 282 | debug? if cr ." go" cr then 283 | go 284 | cr ." end of BOOT-SCRIPT" 285 | """ 286 | 287 | BOOT_SCRIPT = BOOT_SCRIPT.format(**locals()) 288 | BOOT_SCRIPT = html_escape_forth(BOOT_SCRIPT) 289 | 290 | 291 | BITMAP = """ 292 | 0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B 293 | 0BFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0B 294 | 0BFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0B 295 | 0BFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0B 296 | 0BFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0B 297 | 0BFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0B 298 | 0BFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0B 299 | 0BFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF92FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0B 300 | 0BFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF4925B7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0B 301 | 0BFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF92006EDBFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0B 302 | 0BFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFDB0049B7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0B 303 | 0BFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBFBBBFBBBFBBBFBBBFBBBFBBBFBBBFBB252577BFDFDFDFDFDFDFDFDFDFDFDFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0B 304 | 0BFFFFFFFFFFFFFFFFFFFFFFFFFFFF772F332F2F2F332F2F2F332F2F2F332F2A055757575757575B57575B57575B579BFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0B 305 | 0BFFFFFFFFFFFFFFFFFFFFFFFFFFFF772F2F2F332F2F2F332F2F2F332F2F2F012E57575B575B57575757575757575777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0B 306 | 0BFFFFFFFFFFFFFFFFFFFFFFFFFFFF97132F0F2F132F0F2F132F0F2F0F2F0A0557575B5757575B57575B57575B575797FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0B 307 | 0BFFFFFFFFFFFFFFFFFFFFFFFFFFFF772F2F330F2F2F2F0F2F0F2F2F332F052A575B5757535357575B57575B57575B97FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0B 308 | 0BFFFFFFFFFFFFFFFFFFFFFFFFFFFF772F2F2F332F0F2B062F332F132F0A00575757575B25255B5757575B5757575797FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0B 309 | 0BFFFFFFFFFFFFFFFFFFFFFFFFFFFF772F132F0F332F0B060F2F0F2F2F0529575B575B572525575B575757575B575777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0B 310 | 0BFFFFFFFFFFFFFFFFFFFFFFFFFFFF970F2F2F2F0F2F0B262F0F332F0A0053575757575B25255B57575B5757575B5797FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0B 311 | 0BFFFFFFFFFFFFFFFFFFFFFFFFFFFF772F2F132F2F332F0F2F332F2F0501575B575B5757534F57575B57575B57575797FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0B 312 | 0BFFFFFFFFFFFFFFFFFFFFFFFFFFFF772F2F2F132F2F2F2F132F2F0F052A575757575B5757575B57575757575B575797FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0B 313 | 0BFFFFFFFFFFFFFFFFFFFFFFFFFFFF77330F332F0F2F132F2F0F2F2F00535757575B5757575B575757575B57575B5777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0B 314 | 0BFFFFFFFFFFFFFFFFFFFFFFFFFFFF972F2F2F2F332F2F132F2F132A00575B575B57575B5757575B5757575B57575797FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0B 315 | 0BFFFFFFFFFFFFFFFFFFFFFFFFFFFF770F330F330F2F0F2F2F332F05255B575757575B5757575B57575B575757575797FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0B 316 | 0BFFFFFFFFFFFFFFFFFFFFFFFFFFFF972F2F2F2F332F332F0F2F2F052A575B57575757575B5757575B57575B575B5797FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0B 317 | 0BFFFFFFFFFFFFFFFFFFFFFFFFFFFF772F0F330F2F0F2F0F332F33052A5757575757575B5757575B575757575B575777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0B 318 | 0BFFFFFFFFFFFFFFFFFFFFFFFFFFFF772F2F2F332F332F2F2F0F2F050000000000002E57575B5757575B575757575B97FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0B 319 | 0BFFFFFFFFFFFFFFFFFFFFFFFFFFFF77332F132F0F2F0F2F0F332F2A0A2A2A2A050053575B5757575B5757575B575797FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0B 320 | 0BFFFFFFFFFFFFFFFFFFFFFFFFFFFF970F2F2F2F332F332F330F2F0F332F0F330600575757575B5757575B57575B5797FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0B 321 | 0BFFFFFFFFFFFFFFFFFFFFFFFFFFFF772F332F132F0F2F0F2F2F332F2F332F0F2504575B575B57575753575B57575777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0B 322 | 0BFFFFFFFFFFFFFFFFFFFFFFFFFFFF772F2F2F2F0B060A2B0F2F0F332F0F2F33050557575B574F2E2505535757575B97FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0B 323 | 0BFFFFFFFFFFFFFFFFFFFFFFFFFFFF772F0F330F332F2B0A0606060A0B0B2B0B05052A29250005292E575757575B5797FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0B 324 | 0BFFFFFFFFFFFFFFFFFFFFFFFFFFFF970F2F2F2F0F2F132F2F0F2B0A0A060606010025292E53575B57575B575B575797FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0B 325 | 0BFFFFFFFFFFFFFFFFFFFFFFFFFFFF772F330F332F132F2F2F2F2F332F2F2F2F0501575B575757575757575757575777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0B 326 | 0BFFFFFFFFFFFFFFFFFFFFFFFFFFFF77332F2F2F2F2F2F132F0F2F0F2F2F0F2F050057575B575B57575B575B57575B97FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0B 327 | 0BFFFFFFFFFFFFFFFFFFFFFFFFFFFF772F2F2F0F332F132F2F2F332F332F2F332600535B575757575B5757575B575797FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0B 328 | 0BFFFFFFFFFFFFFFFFFFFFFFFFFFFF970F330F332F0F2F2F132F0F2F0F330F2F0A004F57575B5757575B5757575B5797FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0B 329 | 0BFFFFFFFFFFFFFFFFFFFFFFFFFFFF9B332F33332F3333332F333333332F33332F002A77777777777777777777777797FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0B 330 | 0BFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFDBDBDBDBDBDBDBDBDBDBDBDBDBDBFBDB2025B7DBDBDBDBDBDBDBDBDBDBDBDBFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0B 331 | 0BFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF6E00B7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0B 332 | 0BFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF006EFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0B 333 | 0BFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFB7B7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0B 334 | 0BFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0B 335 | 0BFFFFFFFFFFFFFFDBDBFFFFFFFFFFFFFFDBDBFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBB57539BFFFFFFFFFFFF775377DFFFFFFFFFFFFFFFFF0B 336 | 0BFFFFFFFFFFFFFF92006EFFFFFFFFFF6E2592FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF53B7DBDBBB53DFFFFFDF97DBFBBB33FFFFFFFFFFFFFFFF0B 337 | 0BFFFFFFFFFFFFFFFF2525FFFFFFFFFF2525DBFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF3397DBFFFFFFDF33DBFF57B7FFFFFF97DBFFFFFFFFFFFFFF0B 338 | 0BFFFFFFFFFFFFFFFF9225B7FFFFFFB76E25DBFFFFFFFFFFFFFFFFFFFFFFFFFFDBB7FFFFFFFF7733B7FFFFFFFFFF9B53FF3397FFFFFFFFFFFFFFFFFFFFFFFF0B 339 | 0BFFFFFFFFFFFFFFFF92496EFFFFFFB79225DBFFFFB792496EFFFFFFB7926E49FFFFFFFFFFFF2F73FFFFFFFFFFFFDF0FDB5333FFFFFFFFFFFFFFFFFFFFFFFF0B 340 | 0BFFFFFFFFFFFFFFDBB7B725FFFFFF929225DBFF9292FFFF00DBFF6EB7FFFF6E92FFFFFFFFFF0F93FFFFFFFFFFFFFF2F979B2F33DFFFFFFFFFFFFFFFFFFFFF0B 341 | 0BFFFFFFFFFFFFFFDBB7FF00B7FFDBB7B725DBFF25B7FFFF25B7DB49DBFFFFFFB7FFFFFFFFDF0F97FFFFFFFFFFFFFF3373FFBB330F53FFFFFFFFFFFFFFFFFF0B 342 | 0BFFFFFFFFFFFFFFDBDBFF6E49FFB7FFFF00DBFFFFFFFFFF00B74949FFFFFFFFFFFFFFFFFFDF2F97FFFFFFFFFFFFFF3373FFFFFF972F33FFFFFFFFFFFFFFFF0B 343 | 0BFFFFFFFFFFFFFFDBDBFFB725FF92FFFF00DBFFFFFFDB9225B7256EFFFFFFFFFFFFFFFFFFFF2F97FFFFFFFFFFFFFF2F73FFFFFFFFBB2F97FFFFFFFFFFFFFF0B 344 | 0BFFFFFFFFFFFFFFB7DBFFFF006EB7FFFF00B7FFFFB7DBFF25B7256EFFFFFFFFFFFFFFFFFFFF3373FFFFFFFFFFFFDF2F97FFFFFFFFFF7773FFFFFFFFFFFFFF0B 345 | 0BFFFFFFFFFFFFFFB7DBFFFF4925DBFFFF00B7FF6EB7FFFF25B76E49FFFFFFFFFFFFFFFFFFFF9B33FFFFFFFFFFFF5753B7BBFFFFFFFF7773FFFFFFFFFFFFFF0B 346 | 0BFFFFFFFFFFFFFF92DBFFFFDB49DBFFFF00B7FF25B7FFB700B7FF25DBFFFFFFFFFFFFFFFFFFFF5377FFFFFFFFBB3397DF53FFFFFFFF57B7FFFFFFFFFFFFFF0B 347 | 0BFFFFFFFFFFFFDB2549DBFFFFB7FFDB490049DB254992DB2549DB9225DBFF92FFFFFFFFFFFFFFFF5397FFFFBB53B7FBFF3397FFFF77B7DBFFFFFFFFFFFFFF0B 348 | 0BFFFFFFFFFFFFFFB792DBFFFFFFFFFFB7B7B7DBB76EB7FFDB92DBFFB76E6EB7FFFFFFFFFFFFFFFFFFB7737797DBFFFFFFFF977397BBDBFFFFFFFFFFFFFFFF0B 349 | 0BFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0B 350 | 0BFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0B 351 | 0BFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0B 352 | 0BFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0B 353 | 0BFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0B 354 | 0BFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0B 355 | 0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B 356 | """ 357 | 358 | 359 | BADGES = """ 360 | 1010 361 | 000000000000000000ABFE0000000000 362 | 0000000000000000ABFF000000000000 363 | ABABABABABABABABFFABABABABABABAB 364 | AB7F7F7F7F7F7FFF7F2A2A2A2A2A2AAB 365 | AB7F7F7FF17F7FFF542A2AFF2A2A2AAB 366 | AB7F7F7FF17FABFF2A2A2AFF2A2A2AAB 367 | AB7F7F7F7F7FFF7F2A2A2A2A2A2A2AAB 368 | AB7F7F7F7F7FFF542A2A2A2A2A2A2AAB 369 | AB7F7F7F7F7FFFFFFFFF2A2A2A2A2AAB 370 | AB7F7F7F7F7F7F7F7FFF2A2A2A2A2AAB 371 | AB7F7FFFF17F7F7F7FFF2A2AFFFF2AAB 372 | AB7F7F7F7FF1F1F1F1FFFFFF542A2AAB 373 | AB7F7F7F7F7F7F7F7FFF2A2A2A2A2AAB 374 | ABABABABABABABABABFFABABABABABAB 375 | 000000000000000000ABFF0000000000 376 | 00000000000000000000ABFF00000000 377 | 000000000000000000F3FF0000000000 378 | 0000000000000000F3FF000000000000 379 | F3F3F3F3F3F3F3F3FFF3F3F3F3F3F3F3 380 | F3AAAAAAAAAAAAFFAA555555555555F3 381 | F3AAAAAAF4AAAAFF7F5555FF555555F3 382 | F3AAAAAAF4AAF3FF555555FF555555F3 383 | F3AAAAAAAAAAFFAA55555555555555F3 384 | F3AAAAAAAAAAFF7F55555555555555F3 385 | F3AAAAAAAAAAFFFFFFFF5555555555F3 386 | F3AAAAAAAAAAAAAAAAFF5555555555F3 387 | F3AAAAFFF4AAAAAAAAFF5555FFFF55F3 388 | F3AAAAAAAAF4F4F4F4FFFFFF7F5555F3 389 | F3AAAAAAAAAAAAAAAAFF5555555555F3 390 | F3F3F3F3F3F3F3F3F3FFF3F3F3F3F3F3 391 | 000000000000000000F3FF0000000000 392 | 00000000000000000000F3FF00000000 393 | 000000000000000000FFFE0000000000 394 | 0000000000000000FFFF000000000000 395 | FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 396 | FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 397 | FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 398 | FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 399 | FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 400 | FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 401 | FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 402 | FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 403 | FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 404 | FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 405 | FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 406 | FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 407 | 000000000000000000FFFF0000000000 408 | 00000000000000000000FFFF00000000 409 | """ 410 | 411 | 412 | COMPATIBLE_TAG = '\n'.join(COMPATIBLE) 413 | 414 | BOOT_INFO = """ 415 | 416 | 417 | {COMPATIBLE_TAG} 418 | 419 | 420 | MacROM for NewWorld. 421 | 422 | 423 | 424 | {BITMAP} 425 | 426 | 427 | 428 | {BOOT_SCRIPT} 429 | 430 | 431 | {BADGES} 432 | 433 | 434 | """.format(**locals()) 435 | 436 | 437 | BOOT_INFO = '\n'.join(l for l in BOOT_INFO.split('\n') if l) 438 | BOOT_INFO = BOOT_INFO.replace('\n', '\r') 439 | BOOT_INFO += '\r\x04' # CR, EOT 440 | BOOT_INFO = BOOT_INFO.encode('ascii') 441 | 442 | if len(BOOT_INFO) > DATA_OFFSET: 443 | raise ValueError 444 | 445 | # Insert the text 446 | tbxi[:len(BOOT_INFO)] = BOOT_INFO 447 | 448 | 449 | 450 | # Checksum 451 | 452 | cksum = adler32(tbxi) 453 | cksum_str = ('\r\\ h# %08X' % cksum).encode('ascii') 454 | 455 | tbxi.extend(cksum_str) 456 | 457 | 458 | 459 | # Write out. 460 | 461 | with open(out_path, 'wb') as f: 462 | f.write(tbxi) 463 | --------------------------------------------------------------------------------