commit 313177ce2a3d47c5eda932c229aebb6a23673dad Author: Elliot Nunn Date: Sun Feb 18 02:25:11 2018 +0800 Initial commit diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..add933e --- /dev/null +++ b/.gitignore @@ -0,0 +1,7 @@ +.DS_Store +parcels +tbxi +lzss +__pycache__ +*.patch +*.hqx diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..b19151b --- /dev/null +++ b/Makefile @@ -0,0 +1,19 @@ +tbxi: scripts/bootmake.py trampoline.elf parcels + ./scripts/bootmake.py $@ trampoline.elf parcels + SetFile -t tbxi -c chrp $@ || true # macOS only + +# Tomfoolery required to be able to put prclmake.py args in another file +parcels: scripts/prclmake.py scripts/prcltool.py parcel-layout.txt scripts/lzss rom $(shell find pef -type f -not -path '*/\.*') + sh -c "scripts/prclmake.py $@ `sed 's/#.*//' parcel-layout.txt | tr '\n' ' '`" + +scripts/lzss: lzss.c + gcc -O2 -o $@ $< + +clean: + rm -rf parcels tbxi scripts/lzss scripts/__pycache__ *.hqx + find . -type f -name '*.patch' -delete + +# For your convenience (macOS only) + +%.hqx: % scripts/binhexmake.py + scripts/binhexmake.py --data=$< --type=tbxi --creator=chrp --name="Mac OS ROM" $@ diff --git a/README.md b/README.md new file mode 100644 index 0000000..ba07c1d --- /dev/null +++ b/README.md @@ -0,0 +1,20 @@ +The NewWorld ROM +================ + +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. + +Building +-------- + +A basic Unix toolchain is required. + + make tbxi + +Patching +-------- + +Some useful patches to the Open Firmware boot script can be enabled at the top of `bootmake.py`. + +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: + + patchpef.py pef/nlib/NativePowerMgrLib{,.patch} Initialize+0x94 " li r3,0" diff --git a/lzss.c b/lzss.c new file mode 100644 index 0000000..d333b62 --- /dev/null +++ b/lzss.c @@ -0,0 +1,412 @@ +#include +#include +#include + +#define circ(buffer, offset) ((buffer)[(offset) % sizeof(buffer)]) + + +const int lookup_size = 2; +const int thresh_n = 3; +const int max_n = 18; // Four bits of lookup + + + + + +/************************************************************** + LZSS.C -- A Data Compression Program +*************************************************************** + 4/6/1989 Haruhiko Okumura + Use, distribute, and modify this program freely. + Please send me your improved versions. + PC-VAN SCIENCE + NIFTY-Serve PAF01022 + CompuServe 74050,1022 +**************************************************************/ + +#define N 4096 /* size of ring buffer - must be power of 2 */ +#define F 18 /* upper limit for match_length */ +#define THRESHOLD 2 /* encode string into position and length + if match_length is greater than this */ +#define NIL N /* index for root of binary search trees */ + +struct encode_state { + /* + * left & right children & parent. These constitute binary search trees. + */ + int lchild[N + 1], rchild[N + 257], parent[N + 1]; + + /* ring buffer of size N, with extra F-1 bytes to aid string comparison */ + uint8_t text_buf[N + F - 1]; + + /* + * match_length of longest match. + * These are set by the insert_node() procedure. + */ + int match_position, match_length; +}; + + +int +decompress_lzss(uint8_t *dst, uint8_t *src, uint32_t srclen) +{ + /* ring buffer of size N, with extra F-1 bytes to aid string comparison */ + uint8_t text_buf[N + F - 1]; + uint8_t *dststart = dst; + uint8_t *srcend = src + srclen; + int i, j, k, r, c; + unsigned int flags; + + dst = dststart; + srcend = src + srclen; + for (i = 0; i < N - F; i++) + text_buf[i] = ' '; + r = N - F; + flags = 0; + for ( ; ; ) { + if (((flags >>= 1) & 0x100) == 0) { + if (src < srcend) c = *src++; else break; + flags = c | 0xFF00; /* uses higher byte cleverly */ + } /* to count eight */ + if (flags & 1) { + if (src < srcend) c = *src++; else break; + *dst++ = c; + text_buf[r++] = c; + r &= (N - 1); + } else { + if (src < srcend) i = *src++; else break; + if (src < srcend) j = *src++; else break; + i |= ((j & 0xF0) << 4); + j = (j & 0x0F) + THRESHOLD; + for (k = 0; k <= j; k++) { + c = text_buf[(i + k) & (N - 1)]; + *dst++ = c; + text_buf[r++] = c; + r &= (N - 1); + } + } + } + + return dst - dststart; +} + +/* + * initialize state, mostly the trees + * + * For i = 0 to N - 1, rchild[i] and lchild[i] will be the right and left + * children of node i. These nodes need not be initialized. Also, parent[i] + * is the parent of node i. These are initialized to NIL (= N), which stands + * for 'not used.' For i = 0 to 255, rchild[N + i + 1] is the root of the + * tree for strings that begin with character i. These are initialized to NIL. + * Note there are 256 trees. */ +static void init_state(struct encode_state *sp) +{ + int i; + + memset(sp, 0, sizeof(*sp)); + + for (i = 0; i < N - F; i++) + sp->text_buf[i] = ' '; + for (i = N + 1; i <= N + 256; i++) + sp->rchild[i] = NIL; + for (i = 0; i < N; i++) + sp->parent[i] = NIL; +} + +/* + * Inserts string of length F, text_buf[r..r+F-1], into one of the trees + * (text_buf[r]'th tree) and returns the longest-match position and length + * via the global variables match_position and match_length. + * If match_length = F, then removes the old node in favor of the new one, + * because the old one will be deleted sooner. Note r plays double role, + * as tree node and position in buffer. + */ +static void insert_node(struct encode_state *sp, int r) +{ + int i, p, cmp; + uint8_t *key; + + cmp = 1; + key = &sp->text_buf[r]; + p = N + 1 + key[0]; + sp->rchild[r] = sp->lchild[r] = NIL; + sp->match_length = 0; + for ( ; ; ) { + if (cmp >= 0) { + if (sp->rchild[p] != NIL) + p = sp->rchild[p]; + else { + sp->rchild[p] = r; + sp->parent[r] = p; + return; + } + } else { + if (sp->lchild[p] != NIL) + p = sp->lchild[p]; + else { + sp->lchild[p] = r; + sp->parent[r] = p; + return; + } + } + for (i = 1; i < F; i++) { + if ((cmp = key[i] - sp->text_buf[p + i]) != 0) + break; + } + if (i > sp->match_length) { + sp->match_position = p; + if ((sp->match_length = i) >= F) + break; + } + } + sp->parent[r] = sp->parent[p]; + sp->lchild[r] = sp->lchild[p]; + sp->rchild[r] = sp->rchild[p]; + sp->parent[sp->lchild[p]] = r; + sp->parent[sp->rchild[p]] = r; + if (sp->rchild[sp->parent[p]] == p) + sp->rchild[sp->parent[p]] = r; + else + sp->lchild[sp->parent[p]] = r; + sp->parent[p] = NIL; /* remove p */ +} + +/* deletes node p from tree */ +static void delete_node(struct encode_state *sp, int p) +{ + int q; + + if (sp->parent[p] == NIL) + return; /* not in tree */ + if (sp->rchild[p] == NIL) + q = sp->lchild[p]; + else if (sp->lchild[p] == NIL) + q = sp->rchild[p]; + else { + q = sp->lchild[p]; + if (sp->rchild[q] != NIL) { + do { + q = sp->rchild[q]; + } while (sp->rchild[q] != NIL); + sp->rchild[sp->parent[q]] = sp->lchild[q]; + sp->parent[sp->lchild[q]] = sp->parent[q]; + sp->lchild[q] = sp->lchild[p]; + sp->parent[sp->lchild[p]] = q; + } + sp->rchild[q] = sp->rchild[p]; + sp->parent[sp->rchild[p]] = q; + } + sp->parent[q] = sp->parent[p]; + if (sp->rchild[sp->parent[p]] == p) + sp->rchild[sp->parent[p]] = q; + else + sp->lchild[sp->parent[p]] = q; + sp->parent[p] = NIL; +} + +uint8_t * +compress_lzss(uint8_t *dst, uint32_t dstlen, uint8_t *src, uint32_t srcLen) +{ + /* Encoding state, mostly tree but some current match stuff */ + struct encode_state *sp; + + int i, c, len, r, s, last_match_length, code_buf_ptr; + uint8_t code_buf[17], mask; + uint8_t *srcend = src + srcLen; + uint8_t *dstend = dst + dstlen; + + /* initialize trees */ + sp = (struct encode_state *) malloc(sizeof(*sp)); + init_state(sp); + + /* + * code_buf[1..16] saves eight units of code, and code_buf[0] works + * as eight flags, "1" representing that the unit is an unencoded + * letter (1 byte), "" a position-and-length pair (2 bytes). + * Thus, eight units require at most 16 bytes of code. + */ + code_buf[0] = 0; + code_buf_ptr = mask = 1; + + /* Clear the buffer with any character that will appear often. */ + s = 0; r = N - F; + + /* Read F bytes into the last F bytes of the buffer */ + for (len = 0; len < F && src < srcend; len++) + sp->text_buf[r + len] = *src++; + if (!len) { + free(sp); + return (void *) 0; /* text of size zero */ + } + /* + * Insert the F strings, each of which begins with one or more + * 'space' characters. Note the order in which these strings are + * inserted. This way, degenerate trees will be less likely to occur. + */ + for (i = 1; i <= F; i++) + insert_node(sp, r - i); + + /* + * Finally, insert the whole string just read. + * The global variables match_length and match_position are set. + */ + insert_node(sp, r); + do { + /* match_length may be spuriously long near the end of text. */ + if (sp->match_length > len) + sp->match_length = len; + if (sp->match_length <= THRESHOLD) { + sp->match_length = 1; /* Not long enough match. Send one byte. */ + code_buf[0] |= mask; /* 'send one byte' flag */ + code_buf[code_buf_ptr++] = sp->text_buf[r]; /* Send uncoded. */ + } else { + /* Send position and length pair. Note match_length > THRESHOLD. */ + code_buf[code_buf_ptr++] = (uint8_t) sp->match_position; + code_buf[code_buf_ptr++] = (uint8_t) + ( ((sp->match_position >> 4) & 0xF0) + | (sp->match_length - (THRESHOLD + 1)) ); + } + if ((mask <<= 1) == 0) { /* Shift mask left one bit. */ + /* Send at most 8 units of code together */ + for (i = 0; i < code_buf_ptr; i++) + if (dst < dstend) + *dst++ = code_buf[i]; + else { + free(sp); + return (void *) 0; + } + code_buf[0] = 0; + code_buf_ptr = mask = 1; + } + last_match_length = sp->match_length; + for (i = 0; i < last_match_length && src < srcend; i++) { + delete_node(sp, s); /* Delete old strings and */ + c = *src++; + sp->text_buf[s] = c; /* read new bytes */ + + /* + * If the position is near the end of buffer, extend the buffer + * to make string comparison easier. + */ + if (s < F - 1) + sp->text_buf[s + N] = c; + + /* Since this is a ring buffer, increment the position modulo N. */ + s = (s + 1) & (N - 1); + r = (r + 1) & (N - 1); + + /* Register the string in text_buf[r..r+F-1] */ + insert_node(sp, r); + } + while (i++ < last_match_length) { + delete_node(sp, s); + + /* After the end of text, no need to read, */ + s = (s + 1) & (N - 1); + r = (r + 1) & (N - 1); + /* but buffer may not be empty. */ + if (--len) + insert_node(sp, r); + } + } while (len > 0); /* until length of string to be processed is zero */ + + if (code_buf_ptr > 1) { /* Send remaining code. */ + for (i = 0; i < code_buf_ptr; i++) + if (dst < dstend) + *dst++ = code_buf[i]; + else { + free(sp); + return (void *) 0; + } + } + + free(sp); + return dst; +} + + + + + +/* my nasty stuff */ + +// Yes, I know it's a mess. Feel free to clean it up, +// but please don't change the command-line interface. +int main(int argc, char *argv[]) +{ + freopen(NULL, "rb", stdin); + freopen(NULL, "wb", stderr); + + unsigned char dict[0x1000]; + unsigned int dict_i = 0xFEE; + + if(argc == 2 && strcmp(argv[1], "x") == 0) + { + int head_char, lit, offset, len; + + while(1) + { + head_char = getchar(); + if(head_char == EOF) return 0; + + head_char |= 0xFF00; //neat little hack, this + + while(head_char != 0xFF) + { + if(head_char & 1) + { // Literal read (1 char) + lit = getchar(); + if(lit == EOF) return 0; + + circ(dict, dict_i++) = lit; + putchar(lit); + } + else + { // Dictionary read (2 bytes, offset and thingo) + offset = getchar(); + len = getchar(); + if(offset == EOF) return 0; + + offset |= (len & 0xF0) << 4; + len &= 0x0F; + len += 3; + + for(int i=0; i>= 1; + } + } + } + else if(argc == 2 && strcmp(argv[1], "c") == 0) + { + uint8_t *a, *b, *ret; + uint32_t alen; + + a = malloc(0x400000); + b = malloc(0x400000); + if(!a || !b) return 1; + + alen = fread(a, 1, 0x400000, stdin); + + ret = compress_lzss(b, 0x400000, a, alen); + if(!ret) return 1; + + if(fwrite(b, ret-b, 1, stdout) != 1) return 1; + if(fclose(stdout)) return 1; + + return 0; + } + else + { + fprintf(stderr, "USAGE: lzss [x|c]\n"); + return 1; + } +} + +#define BUF_SIZE 512 +#define BUF_MIN 128 diff --git a/parcel-layout.txt b/parcel-layout.txt new file mode 100644 index 0000000..51f97d4 --- /dev/null +++ b/parcel-layout.txt @@ -0,0 +1,144 @@ +# These are arguments to prclmake.py, which get put through a hacky process in the Makefile. +# Basically, from # to EOL gets deleted, and newlines become spaces. + +--prcl -f=00020000 -t=node -n="CodePrepare Node Parcel" -c= + --bin -f=00000000 -t=cstr -n=name --data AAPL,CodePrepare + --bin -f=00000000 -t=csta -n=AAPL,prepare_order --data Placeholder + --bin -f=00020094 -t=nlib -n=TimeManagerLib -l --src=pef/nlib/TimeManagerLib + --bin -f=00020094 -t=nlib -n=NVRAMServicesLib -l --src=pef/nlib/NVRAMServicesLib + --bin -f=00020094 -t=nlib -n=RTCServicesLib -l --src=pef/nlib/RTCServicesLib + +--prcl -f=00010000 -t=node -n="CodeRegister Node Parcel" -c= + --bin -f=00000000 -t=cstr -n=name --data AAPL,CodeRegister + --bin -f=00010094 -t=nlib -n=NativePowerMgrLib -l --src=pef/nlib/NativePowerMgrLib + --bin -f=00010094 -t=nlib -n=AGPLib -l --src=pef/nlib/AGPLib + --bin -f=00010194 -t=nlib -n=EtherPrintfLib -l --src=pef/nlib/EtherPrintfLib + --bin -f=00010094 -t=shlb -n=StartLib -l --src=pef/shlb/StartLib + +--prcl -f=00000000 -t="rom " -n="Mac OS ROM Parcel" -c= + --bin -f=00000005 -t="rom " -n= -l --src=rom + +--prcl -f=00000000 -t=psum -n="Property Checksum" -c= + --bin -f=00000000 -t=csta -n= --data + name + model + compatible + device_type + reg + assigned-addresses + slot-names + vendor-id + device-id + class-code + devsel-speed + fast-back-to-back + bootpath + mac-address + --bin -f=00000000 -t=csta -n= --data + boot-rom + macos + --bin -f=00000000 -t=csta -n= --data + Placeholder + --bin -f=00000000 -t=csta -n= --data + Placeholder + --bin -f=00000000 -t=csta -n= --data + usb + ieee1394 + +--prcl -f=0000000c -t=prop -n=apple21143 -c=network + --bin -f=00000006 -t=shlb -n=lanLib,AAPL,MacOS,PowerPC -l --src=pef/shlb/lanLib/apple21143 + +--prcl -f=00000009 -t=prop -n=backlight -c=backlight + --bin -f=00000000 -t=ndrv -n=driver,AAPL,MacOS,PowerPC --src=pef/ndrv/BacklightDriver --nosum + --bin -f=00000002 -t=cstr -n=code,AAPL,MacOS,name --data BacklightDriver + +--prcl -f=0000000c -t=prop -n=bmac+ -c=network + --bin -f=00000006 -t=shlb -n=lanLib,AAPL,MacOS,PowerPC -l --src=pef/shlb/lanLib/bmac+ + +--prcl -f=0000000c -t=prop -n=cmd646-ata -c=ata + --bin -f=00000006 -t=ndrv -n=driver,AAPL,MacOS,PowerPC -l --src=pef/ndrv/ata/cmd646 + +--prcl -f=00000008 -t=prop -n=cofb -c=display + --bin -f=00000024 -t=ndrv -n=driver,AAPL,MacOS,PowerPC -l --src=pef/ndrv/display + +--prcl -f=0000000c -t=prop -n=cuda -c=via-cuda + --bin -f=00000000 -t=ndrv -n=pef,AAPL,MacOS,PowerPC,register -l --src=pef/ndrv/PowerMgrPlugin/cuda --nosum + --bin -f=00000002 -t=cstr -n=code,AAPL,MacOS,name --data PowerMgrPlugin + +--prcl -f=0000000c -t=prop -n=gmac -c=network + --bin -f=00000006 -t=shlb -n=lanLib,AAPL,MacOS,PowerPC -l --src=pef/shlb/lanLib/gmac + +--prcl -f=0000000c -t=prop -n=grackle -c=pci + --bin -f=00000016 -t=nlib -n=pef,AAPL,MacOS,PowerPC,prepare -l --src=pef/nlib/PCICyclesLib/Grackle + --bin -f=00000000 -t=cstr -n=code,AAPL,MacOS,name --data Grackle_PCICyclesLib + +--prcl -f=0000000c -t=prop -n=heathrow-ata -c=ide + --bin -f=00000006 -t=ndrv -n=driver,AAPL,MacOS,PowerPC -l --src=pef/ndrv/ata/heathrow + +--prcl -f=0000000c -t=prop -n=heathrow-ata -c=ata + --bin -f=00000002 -t=ndrv -n=driver,AAPL,MacOS,PowerPC -l --src=pef/ndrv/ata/heathrow --backref + +--prcl -f=0000000c -t=prop -n=kauai-ata -c=ata + --bin -f=00000006 -t=ndrv -n=driver,AAPL,MacOS,PowerPC -l --src=pef/ndrv/ata/kauai + +--prcl -f=0000000c -t=prop -n=keylargo-ata -c=ata + --bin -f=00000006 -t=ndrv -n=driver,AAPL,MacOS,PowerPC -l --src=pef/ndrv/ata/keylargo + +--prcl -f=0000000c -t=prop -n=keywest-i2c -c=i2c + --bin -f=00000006 -t=ndrv -n=driver,AAPL,MacOS,PowerPC -l --src=pef/ndrv/i2c + +--prcl -f=0000000a -t=prop -n=mac-io -c=nvram + --bin -f=00000004 -t=ndrv -n=driver,AAPL,MacOS,PowerPC -l --src=pef/ndrv/nvram/mac-io + +--prcl -f=00000001 -t=prop -n=macos -c= + --bin -f=00000000 -t=cstr -n=MacOSROMFile-version --data 9.6f1 + +--prcl -f=0000000c -t=prop -n=nvram,flash -c=nvram + --bin -f=00000004 -t=ndrv -n=driver,AAPL,MacOS,PowerPC -l --src=pef/ndrv/nvram/flash + +--prcl -f=0000000c -t=prop -n=pci104c,ac1a -c=cardbus + --bin -f=00000016 -t=ndrv -n=driver,AAPL,MacOS,PowerPC -l --src=pef/ndrv/cardbus + --bin -f=00010094 -t=nlib -n=PCCard -l --src=pef/nlib/PCCardLib + +--prcl -f=0000000c -t=prop -n=pci104c,ac50 -c=cardbus + --bin -f=00000016 -t=ndrv -n=driver,AAPL,MacOS,PowerPC -l --src=pef/ndrv/cardbus --backref + --bin -f=00010094 -t=nlib -n=PCCard -l --src=pef/nlib/PCCardLib + +--prcl -f=0000020c -t=prop -n=pciclass,0c0010 -c=ieee1394 + --bin -f=00000004 -t=ndrv -n=driver,AAPL,MacOS,PowerPC -l --src=pef/ndrv/firewire + --bin -f=00010096 -t=nlib -n=FWServicesLib -l --src=pef/nlib/FWServicesLib + --bin -f=00010096 -t=nlib -n=DevNLib -l --src=pef/nlib/DevNLib + --bin -f=00010096 -t=nlib -n=DFMLib -l --src=pef/nlib/DFMLib + --bin -f=00010096 -t=nlib -n=GenericDriverFamily -l --src=pef/nlib/GenericDriverFamily + +--prcl -f=0000000c -t=prop -n=pmu -c=power-mgt + --bin -f=00000000 -t=ndrv -n=pef,AAPL,MacOS,PowerPC,register -l --src=pef/ndrv/PowerMgrPlugin/pmu --nosum + --bin -f=00000002 -t=cstr -n=code,AAPL,MacOS,name --data PowerMgrPlugin --backref + --bin -f=00000002 -t=cstr -n=target-mode-capable --data SCSI + --bin -f=00010096 -t=nlib -n=PMULib -l --src=pef/nlib/PMULib + +--prcl -f=0000000c -t=prop -n=uni-n-i2c -c=i2c + --bin -f=00000006 -t=ndrv -n=driver,AAPL,MacOS,PowerPC -l --src=pef/ndrv/i2c + +--prcl -f=0000000c -t=prop -n=uni-north -c=pci + --bin -f=00000016 -t=nlib -n=pef,AAPL,MacOS,PowerPC,prepare -l --src=pef/nlib/PCICyclesLib/UniNorth + --bin -f=00000002 -t=cstr -n=code,AAPL,MacOS,name --data UniNorth_PCICyclesLib + +--prcl -f=0000000a -t=prop -n=via-cuda -c=rtc + --bin -f=00000004 -t=ndrv -n=driver,AAPL,MacOS,PowerPC -l --src=pef/ndrv/rtc/via-cuda + +--prcl -f=0000000a -t=prop -n=via-pmu -c=nvram + --bin -f=00000004 -t=ndrv -n=driver,AAPL,MacOS,PowerPC -l --src=pef/ndrv/nvram/via-pmu + +--prcl -f=0000000a -t=prop -n=via-pmu -c=rtc + --bin -f=00000004 -t=ndrv -n=driver,AAPL,MacOS,PowerPC -l --src=pef/ndrv/rtc/via-pmu + +--prcl -f=0000000c -t=prop -n=via-pmu-2000 -c=power-mgt + --bin -f=00000000 -t=ndrv -n=pef,AAPL,MacOS,PowerPC,register -l --src=pef/ndrv/PowerMgrPlugin/pmu-2000 --nosum + --bin -f=00000002 -t=cstr -n=code,AAPL,MacOS,name --data PowerMgrPlugin --backref + --bin -f=00010096 -t=nlib -n=PMULib -l --src=pef/nlib/PMULib --backref + +--prcl -f=0000000c -t=prop -n=via-pmu-99 -c=power-mgt + --bin -f=00000000 -t=ndrv -n=pef,AAPL,MacOS,PowerPC,register -l --src=pef/ndrv/PowerMgrPlugin/pmu-99 --nosum + --bin -f=00000002 -t=cstr -n=code,AAPL,MacOS,name --data PowerMgrPlugin --backref + --bin -f=00010096 -t=nlib -n=PMULib -l --src=pef/nlib/PMULib --backref diff --git a/pef/ndrv/BacklightDriver b/pef/ndrv/BacklightDriver new file mode 100644 index 0000000..5c666be Binary files /dev/null and b/pef/ndrv/BacklightDriver differ diff --git a/pef/ndrv/PowerMgrPlugin/cuda b/pef/ndrv/PowerMgrPlugin/cuda new file mode 100644 index 0000000..0189bf8 Binary files /dev/null and b/pef/ndrv/PowerMgrPlugin/cuda differ diff --git a/pef/ndrv/PowerMgrPlugin/pmu b/pef/ndrv/PowerMgrPlugin/pmu new file mode 100644 index 0000000..b6b5ac5 Binary files /dev/null and b/pef/ndrv/PowerMgrPlugin/pmu differ diff --git a/pef/ndrv/PowerMgrPlugin/pmu-2000 b/pef/ndrv/PowerMgrPlugin/pmu-2000 new file mode 100644 index 0000000..2628d46 Binary files /dev/null and b/pef/ndrv/PowerMgrPlugin/pmu-2000 differ diff --git a/pef/ndrv/PowerMgrPlugin/pmu-99 b/pef/ndrv/PowerMgrPlugin/pmu-99 new file mode 100644 index 0000000..0456d35 Binary files /dev/null and b/pef/ndrv/PowerMgrPlugin/pmu-99 differ diff --git a/pef/ndrv/ata/cmd646 b/pef/ndrv/ata/cmd646 new file mode 100644 index 0000000..f44c2ee Binary files /dev/null and b/pef/ndrv/ata/cmd646 differ diff --git a/pef/ndrv/ata/heathrow b/pef/ndrv/ata/heathrow new file mode 100644 index 0000000..ceeb88d Binary files /dev/null and b/pef/ndrv/ata/heathrow differ diff --git a/pef/ndrv/ata/kauai b/pef/ndrv/ata/kauai new file mode 100644 index 0000000..4486836 Binary files /dev/null and b/pef/ndrv/ata/kauai differ diff --git a/pef/ndrv/ata/keylargo b/pef/ndrv/ata/keylargo new file mode 100644 index 0000000..9664968 Binary files /dev/null and b/pef/ndrv/ata/keylargo differ diff --git a/pef/ndrv/cardbus b/pef/ndrv/cardbus new file mode 100644 index 0000000..52d3a23 Binary files /dev/null and b/pef/ndrv/cardbus differ diff --git a/pef/ndrv/display b/pef/ndrv/display new file mode 100644 index 0000000..1678b03 Binary files /dev/null and b/pef/ndrv/display differ diff --git a/pef/ndrv/firewire b/pef/ndrv/firewire new file mode 100644 index 0000000..c76d8f6 Binary files /dev/null and b/pef/ndrv/firewire differ diff --git a/pef/ndrv/i2c b/pef/ndrv/i2c new file mode 100644 index 0000000..c642a4b Binary files /dev/null and b/pef/ndrv/i2c differ diff --git a/pef/ndrv/nvram/flash b/pef/ndrv/nvram/flash new file mode 100644 index 0000000..43cc96a Binary files /dev/null and b/pef/ndrv/nvram/flash differ diff --git a/pef/ndrv/nvram/mac-io b/pef/ndrv/nvram/mac-io new file mode 100644 index 0000000..94fda4f Binary files /dev/null and b/pef/ndrv/nvram/mac-io differ diff --git a/pef/ndrv/nvram/via-pmu b/pef/ndrv/nvram/via-pmu new file mode 100644 index 0000000..0c2dc8f Binary files /dev/null and b/pef/ndrv/nvram/via-pmu differ diff --git a/pef/ndrv/rtc/via-cuda b/pef/ndrv/rtc/via-cuda new file mode 100644 index 0000000..d6cdb6e Binary files /dev/null and b/pef/ndrv/rtc/via-cuda differ diff --git a/pef/ndrv/rtc/via-pmu b/pef/ndrv/rtc/via-pmu new file mode 100644 index 0000000..e09c8b6 Binary files /dev/null and b/pef/ndrv/rtc/via-pmu differ diff --git a/pef/nlib/AGPLib b/pef/nlib/AGPLib new file mode 100644 index 0000000..54a951d Binary files /dev/null and b/pef/nlib/AGPLib differ diff --git a/pef/nlib/DFMLib b/pef/nlib/DFMLib new file mode 100644 index 0000000..dea6be0 Binary files /dev/null and b/pef/nlib/DFMLib differ diff --git a/pef/nlib/DevNLib b/pef/nlib/DevNLib new file mode 100644 index 0000000..b2c3400 Binary files /dev/null and b/pef/nlib/DevNLib differ diff --git a/pef/nlib/EtherPrintfLib b/pef/nlib/EtherPrintfLib new file mode 100644 index 0000000..34240d4 Binary files /dev/null and b/pef/nlib/EtherPrintfLib differ diff --git a/pef/nlib/FWServicesLib b/pef/nlib/FWServicesLib new file mode 100644 index 0000000..8a465cc Binary files /dev/null and b/pef/nlib/FWServicesLib differ diff --git a/pef/nlib/GenericDriverFamily b/pef/nlib/GenericDriverFamily new file mode 100644 index 0000000..8faf892 Binary files /dev/null and b/pef/nlib/GenericDriverFamily differ diff --git a/pef/nlib/NVRAMServicesLib b/pef/nlib/NVRAMServicesLib new file mode 100644 index 0000000..8f6f637 Binary files /dev/null and b/pef/nlib/NVRAMServicesLib differ diff --git a/pef/nlib/NativePowerMgrLib b/pef/nlib/NativePowerMgrLib new file mode 100644 index 0000000..4d818ba Binary files /dev/null and b/pef/nlib/NativePowerMgrLib differ diff --git a/pef/nlib/PCCardLib b/pef/nlib/PCCardLib new file mode 100644 index 0000000..95fe17f Binary files /dev/null and b/pef/nlib/PCCardLib differ diff --git a/pef/nlib/PCICyclesLib/Grackle b/pef/nlib/PCICyclesLib/Grackle new file mode 100644 index 0000000..298636a Binary files /dev/null and b/pef/nlib/PCICyclesLib/Grackle differ diff --git a/pef/nlib/PCICyclesLib/UniNorth b/pef/nlib/PCICyclesLib/UniNorth new file mode 100644 index 0000000..b0ee186 Binary files /dev/null and b/pef/nlib/PCICyclesLib/UniNorth differ diff --git a/pef/nlib/PMULib b/pef/nlib/PMULib new file mode 100644 index 0000000..9a7b8c4 Binary files /dev/null and b/pef/nlib/PMULib differ diff --git a/pef/nlib/RTCServicesLib b/pef/nlib/RTCServicesLib new file mode 100644 index 0000000..76fab4b Binary files /dev/null and b/pef/nlib/RTCServicesLib differ diff --git a/pef/nlib/TimeManagerLib b/pef/nlib/TimeManagerLib new file mode 100644 index 0000000..75a1c8c Binary files /dev/null and b/pef/nlib/TimeManagerLib differ diff --git a/pef/shlb/StartLib b/pef/shlb/StartLib new file mode 100644 index 0000000..ba21faa Binary files /dev/null and b/pef/shlb/StartLib differ diff --git a/pef/shlb/lanLib/apple21143 b/pef/shlb/lanLib/apple21143 new file mode 100644 index 0000000..6f7ab6a Binary files /dev/null and b/pef/shlb/lanLib/apple21143 differ diff --git a/pef/shlb/lanLib/bmac+ b/pef/shlb/lanLib/bmac+ new file mode 100644 index 0000000..8324dab Binary files /dev/null and b/pef/shlb/lanLib/bmac+ differ diff --git a/pef/shlb/lanLib/gmac b/pef/shlb/lanLib/gmac new file mode 100644 index 0000000..018467d Binary files /dev/null and b/pef/shlb/lanLib/gmac differ diff --git a/rom b/rom new file mode 100644 index 0000000..10e632a Binary files /dev/null and b/rom differ diff --git a/scripts/binhexmake.py b/scripts/binhexmake.py new file mode 100755 index 0000000..14e7e59 --- /dev/null +++ b/scripts/binhexmake.py @@ -0,0 +1,61 @@ +#!/usr/bin/env python3 + + +import binhex +import argparse +import os.path + + +def get_file(filename): + with open(filename, 'rb') as f: + return f.read() + + +def fourcc(s): + b = s.encode('ascii').ljust(4, b' ') + if len(b) != 4: + raise ValueError('wrong length') + return b + + +parser = argparse.ArgumentParser( + description = """Blah.""" +) + +parser.add_argument('--data', action='store', metavar='FILE', help='Data fork') +parser.add_argument('--rsrc', action='store', metavar='FILE', help='Resource fork') +parser.add_argument('--type', action='store', metavar='FOURCC', type=fourcc, default=' ', help='(space-padded) type code') +parser.add_argument('--creator', action='store', metavar='FOURCC', type=fourcc, default=' ', help='(space-padded) creator code') +parser.add_argument('--name', action='store', metavar='FILENAME', default='', help='archived name (taken from DEST by default)') +parser.add_argument('--has-bundle', action='store_true', help='set Finder flag indicating BNDL resource present') +parser.add_argument('dest', metavar='DEST', help='HQX file') + +args = parser.parse_args() + + +# make an auto filename +if args.name: + name = args.name +else: + name = os.path.basename(args.dest) + + base, ext = os.path.splitext(name) + if ext.lower() == '.hqx': + name = base + +assert name + +finfo = binhex.FInfo() +finfo.Creator = args.creator +finfo.Type = args.type +finfo.Flags = 0x2000 if args.has_bundle else 0 + +rsrc_fork, data_fork = (get_file(f) if f else b'' for f in [args.rsrc, args.data]) + + +bh = binhex.BinHex((name, finfo, len(data_fork), len(rsrc_fork)), args.dest) + +bh.write(data_fork) +bh.write_rsrc(rsrc_fork) + +bh.close() diff --git a/scripts/bootmake.py b/scripts/bootmake.py new file mode 100755 index 0000000..507f7da --- /dev/null +++ b/scripts/bootmake.py @@ -0,0 +1,415 @@ +#!/usr/bin/env python3 + +from zlib import adler32 +from sys import argv +from html import escape as html_escape +import re + +def html_escape_forth(f): + return re.sub(r'[<>]+', lambda m: html_escape(m.group()), f) + + + +# Set constants. + +# The COMPATIBLE field at the top of the script +COMPATIBLE = [ + "MacRISC", + # "MacRISC2", + # "MacRISC3", +] + +# Changes to the Forth boot script, all off by default +DELETE_MODEL_CHECK = False +DELETE_CHECKSUM_CHECK = False +MAC_MINI_PRETEND_TO_BE_POWERBOOK = False +G4_FIX = False + +# Adds code to set the AAPL,debug property early in the boot script +DEBUG_PROPERTY = 0 +# DEBUG_PROPERTY |= 0x00000001 # Print general informative messages. +# DEBUG_PROPERTY |= 0x00000002 # Print formatted Mac OS tables (except config/universal info). +# DEBUG_PROPERTY |= 0x00000004 # Print formatted config info table. +# DEBUG_PROPERTY |= 0x00000008 # Dump Mac OS tables (except config/universal info). +# DEBUG_PROPERTY |= 0x00000010 # Print node names while copying the device tree. +# DEBUG_PROPERTY |= 0x00000020 # Print property info while copying the device tree. +# DEBUG_PROPERTY |= 0x00000040 # Print interrupt-related info. +# DEBUG_PROPERTY |= 0x00000080 # Print interrupt tree traversal info. +# DEBUG_PROPERTY |= 0x00000100 # Print address resolution info. +# DEBUG_PROPERTY |= 0x00000200 # Print NV-RAM info. +# DEBUG_PROPERTY |= 0x00000400 # Print Mac OS "universal" info. +# DEBUG_PROPERTY |= 0x00000800 # Print "special" node info. +# DEBUG_PROPERTY |= 0x00001000 # Load EtherPrintf utility via parcel for post FCode debugging. +# DEBUG_PROPERTY |= 0x00002000 # Print BOOTP/DHCP/BSDP information. +# DEBUG_PROPERTY |= 0x00004000 # Allocate writable ROM aperture. +# DEBUG_PROPERTY |= 0x00008000 # Mark Toolbox image as non-cacheable. +# DEBUG_PROPERTY |= 0x00010000 # Print parcel info while copying the device tree. +# DEBUG_PROPERTY |= 0x00020000 # Print information on device tree data checksums. +# DEBUG_PROPERTY |= 0x01000000 # Enable the Nanokernel debugger. +# DEBUG_PROPERTY |= 0x02000000 # Display the Nanokernel log during boot. +# DEBUG_PROPERTY |= 0x10000000 # Dont attempt to unhibernate system. +# DEBUG_PROPERTY |= 0x40000000 # Halt after end of FCode (useful if outputting to screen). + +# The OF-friendly parts of the file are padded out to 20k with nulls +DATA_OFFSET = 0x5000 + + + +# Load the two binary blobs, and save their offsets and sizes. + +out_path, elf_path, parcels_path = argv[1:] + + +tbxi = bytearray(DATA_OFFSET) + +for x in ['elf', 'parcels']: + locals()[x + '_offset'] = len(tbxi) + with open(locals()[x + '_path'], 'rb') as f: + data = f.read() + while len(data) % 4: + data.extend(b'\x00') + locals()[x + '_size'] = len(data) + + tbxi.extend(data) + +info_size = len(tbxi) + + + +# Assemble the CHRP-BOOT text for Open Firmware to parse. + +BOOT_SCRIPT = '' + +if DEBUG_PROPERTY: BOOT_SCRIPT += """ +\ DEBUG_PROPERTY +dev / +%X encode-int " AAPL,debug" property +device-end +\ END DEBUG_PROPERTY +""" % DEBUG_PROPERTY + +if MAC_MINI_PRETEND_TO_BE_POWERBOOK: BOOT_SCRIPT += """ +\ MAC_MINI_PRETEND_TO_BE_POWERBOOK +dev / +" PowerBook4,3" encode-string " model" property +" PowerBook4,3" encode-string " MacRISC" encode-string encode+ " MacRiSC2" encode-string encode+ " MacRISC3" encode-string encode+ " Power Macintosh" encode-string encode+ " compatible" property +device-end +\ END MAC_MINI_PRETEND_TO_BE_POWERBOOK +""" + +if G4_FIX: BOOT_SCRIPT += """ +\ G4_FIX: +" /cpus/PowerPC,G4@0" find-package if + " /cpus/PowerPC,G4@0" select-dev + " cpu-version" active-package get-package-property 0= if + decode-int + 2swap + 2drop + 80010201 < + 0= if + 80010201 encode-int " cpu-version" property + then + then + device-end +then +\ END G4_FIX +""" + +BOOT_SCRIPT += """ +here >r +dev / +""" + +if DELETE_MODEL_CHECK: BOOT_SCRIPT += """ +\ Model check deleted +""" +else: BOOT_SCRIPT += """ +" model" active-package get-package-property abort" can't find MODEL" +decode-string 2swap 2drop " iMac,1" $= ?dup 0= if + " compatible" active-package get-package-property abort" can't find COMPATIBLE" + false >r + begin + dup while + decode-string here over 2swap bounds ?do + i c@ dup [char] A [char] Z between if h# 20 xor then c, + loop +%s + 2drop + repeat + 2drop r> + then +r> here - allot +0= abort" this image is not for this platform" +""" % '\n'.join(' 2dup " %s" $= r> or >r' % m.lower() for m in COMPATIBLE) + +if DELETE_CHECKSUM_CHECK: BOOT_SCRIPT += """ +\ Checksum check deleted +""" +else: BOOT_SCRIPT += """ +decimal +1 load-base load-size 14 - adler32 load-base load-size + 12 - 12 ['] eval catch if + 2drop ." , bad checksum value" -1 + then + <> if + ." , checksum error" + abort + then +hex +""" + +BOOT_SCRIPT += """ +dev /openprom +0 0 " supports-bootinfo" property device-end + +" /chosen" find-package 0= abort" can't find '/chosen'" constant /chosen +" memory" /chosen get-package-property abort" memory??" decode-int constant xmem 2drop +" mmu" /chosen get-package-property abort" mmu??" decode-int constant xmmu 2drop +" AAPL,debug" " /" find-package 0= abort" can't find '/'" get-package-property if + false + else + 2drop true + then + constant debug? +debug? if cr ." checking for RELEASE-LOAD-AREA" then +" release-load-area" $find 0= if 2drop false then constant 'release-load-area +debug? if 'release-load-area if ." , found it" else ." , not found" then then +: do-translate " translate" xmmu $call-method ; +: do-map " map" xmmu $call-method ; +: do-unmap " unmap" xmmu $call-method ; +: claim-mem " claim" xmem $call-method ; +: release-mem " release" xmem $call-method ; +: claim-virt " claim" xmmu $call-method ; +: release-virt " release" xmmu $call-method ; +1000 constant pagesz +pagesz 1- constant pagesz-1 +-1000 constant pagemask +h# {elf_offset:06X} constant elf-offset +h# {elf_size:06X} constant elf-size +elf-size pagesz-1 + pagemask and constant elf-pages +h# {parcels_offset:06X} constant parcels-offset +h# {parcels_size:06X} constant parcels-size +parcels-size pagesz-1 + pagemask and constant parcels-pages +h# {info_size:06X} constant info-size +info-size pagesz-1 + pagemask and constant info-pages +0 value load-base-claim +0 value info-base +'release-load-area if + load-base to info-base + else + load-base info-pages 0 ['] claim-mem catch if 3drop 0 then to load-base-claim + info-pages 1000 claim-virt to info-base + load-base info-base info-pages 10 do-map then +\ allocate room for both images +parcels-pages 400000 claim-mem constant rom-phys parcels-pages 1000 claim-virt constant rom-virt rom-phys rom-virt parcels-pages 10 do-map +elf-pages 1000 claim-mem constant elf-phys elf-pages 1000 claim-virt constant elf-virt +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 +\ copy the compressed image +debug? if cr ." copying compressed ROM image" then +rom-virt parcels-pages 0 fill +info-base parcels-offset + rom-virt parcels-size move +'release-load-area 0= if + info-base info-pages do-unmap load-base-claim ?dup if info-pages release-mem then + then +debug? if cr ." MacOS-ROM phys,virt,size: " rom-phys u. ." , " rom-virt u. ." , " parcels-size u. then +\ create the actual property +debug? if cr ." finding/creating '/rom/macos' package" then +device-end 0 to my-self +" /rom" find-device +" macos" ['] find-device catch if 2drop new-device " macos" device-name finish-device then +" /rom/macos" find-device +debug? if cr ." creating 'AAPL,toolbox-parcels' property" then +rom-virt encode-int parcels-size encode-int encode+ " AAPL,toolbox-parcels" property +device-end +debug? if cr ." copying MacOS.elf to load-base" then +'release-load-area if + load-base elf-pages + 'release-load-area execute + else + load-base elf-pages 0 claim-mem + load-base dup elf-pages 0 do-map then +elf-virt load-base elf-size move +elf-virt elf-pages do-unmap elf-virt elf-pages release-virt +elf-phys elf-pages release-mem +debug? if cr ." init-program" then +init-program +debug? if cr ." .registers" .registers then +debug? if cr ." go" cr then +go +cr ." end of BOOT-SCRIPT" +""" + +BOOT_SCRIPT = BOOT_SCRIPT.format(**locals()) +BOOT_SCRIPT = html_escape_forth(BOOT_SCRIPT) + + +BITMAP = """ +0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B +0BFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0B +0BFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0B +0BFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0B +0BFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0B +0BFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0B +0BFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0B +0BFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF92FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0B +0BFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF4925B7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0B +0BFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF92006EDBFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0B +0BFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFDB0049B7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0B +0BFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBFBBBFBBBFBBBFBBBFBBBFBBBFBBBFBB252577BFDFDFDFDFDFDFDFDFDFDFDFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0B +0BFFFFFFFFFFFFFFFFFFFFFFFFFFFF772F332F2F2F332F2F2F332F2F2F332F2A055757575757575B57575B57575B579BFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0B +0BFFFFFFFFFFFFFFFFFFFFFFFFFFFF772F2F2F332F2F2F332F2F2F332F2F2F012E57575B575B57575757575757575777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0B +0BFFFFFFFFFFFFFFFFFFFFFFFFFFFF97132F0F2F132F0F2F132F0F2F0F2F0A0557575B5757575B57575B57575B575797FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0B +0BFFFFFFFFFFFFFFFFFFFFFFFFFFFF772F2F330F2F2F2F0F2F0F2F2F332F052A575B5757535357575B57575B57575B97FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0B +0BFFFFFFFFFFFFFFFFFFFFFFFFFFFF772F2F2F332F0F2B062F332F132F0A00575757575B25255B5757575B5757575797FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0B +0BFFFFFFFFFFFFFFFFFFFFFFFFFFFF772F132F0F332F0B060F2F0F2F2F0529575B575B572525575B575757575B575777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0B +0BFFFFFFFFFFFFFFFFFFFFFFFFFFFF970F2F2F2F0F2F0B262F0F332F0A0053575757575B25255B57575B5757575B5797FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0B +0BFFFFFFFFFFFFFFFFFFFFFFFFFFFF772F2F132F2F332F0F2F332F2F0501575B575B5757534F57575B57575B57575797FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0B +0BFFFFFFFFFFFFFFFFFFFFFFFFFFFF772F2F2F132F2F2F2F132F2F0F052A575757575B5757575B57575757575B575797FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0B +0BFFFFFFFFFFFFFFFFFFFFFFFFFFFF77330F332F0F2F132F2F0F2F2F00535757575B5757575B575757575B57575B5777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0B +0BFFFFFFFFFFFFFFFFFFFFFFFFFFFF972F2F2F2F332F2F132F2F132A00575B575B57575B5757575B5757575B57575797FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0B +0BFFFFFFFFFFFFFFFFFFFFFFFFFFFF770F330F330F2F0F2F2F332F05255B575757575B5757575B57575B575757575797FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0B +0BFFFFFFFFFFFFFFFFFFFFFFFFFFFF972F2F2F2F332F332F0F2F2F052A575B57575757575B5757575B57575B575B5797FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0B +0BFFFFFFFFFFFFFFFFFFFFFFFFFFFF772F0F330F2F0F2F0F332F33052A5757575757575B5757575B575757575B575777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0B +0BFFFFFFFFFFFFFFFFFFFFFFFFFFFF772F2F2F332F332F2F2F0F2F050000000000002E57575B5757575B575757575B97FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0B +0BFFFFFFFFFFFFFFFFFFFFFFFFFFFF77332F132F0F2F0F2F0F332F2A0A2A2A2A050053575B5757575B5757575B575797FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0B +0BFFFFFFFFFFFFFFFFFFFFFFFFFFFF970F2F2F2F332F332F330F2F0F332F0F330600575757575B5757575B57575B5797FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0B +0BFFFFFFFFFFFFFFFFFFFFFFFFFFFF772F332F132F0F2F0F2F2F332F2F332F0F2504575B575B57575753575B57575777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0B +0BFFFFFFFFFFFFFFFFFFFFFFFFFFFF772F2F2F2F0B060A2B0F2F0F332F0F2F33050557575B574F2E2505535757575B97FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0B +0BFFFFFFFFFFFFFFFFFFFFFFFFFFFF772F0F330F332F2B0A0606060A0B0B2B0B05052A29250005292E575757575B5797FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0B +0BFFFFFFFFFFFFFFFFFFFFFFFFFFFF970F2F2F2F0F2F132F2F0F2B0A0A060606010025292E53575B57575B575B575797FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0B +0BFFFFFFFFFFFFFFFFFFFFFFFFFFFF772F330F332F132F2F2F2F2F332F2F2F2F0501575B575757575757575757575777FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0B +0BFFFFFFFFFFFFFFFFFFFFFFFFFFFF77332F2F2F2F2F2F132F0F2F0F2F2F0F2F050057575B575B57575B575B57575B97FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0B +0BFFFFFFFFFFFFFFFFFFFFFFFFFFFF772F2F2F0F332F132F2F2F332F332F2F332600535B575757575B5757575B575797FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0B +0BFFFFFFFFFFFFFFFFFFFFFFFFFFFF970F330F332F0F2F2F132F0F2F0F330F2F0A004F57575B5757575B5757575B5797FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0B +0BFFFFFFFFFFFFFFFFFFFFFFFFFFFF9B332F33332F3333332F333333332F33332F002A77777777777777777777777797FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0B +0BFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFDBDBDBDBDBDBDBDBDBDBDBDBDBDBFBDB2025B7DBDBDBDBDBDBDBDBDBDBDBDBFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0B +0BFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF6E00B7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0B +0BFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF006EFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0B +0BFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFB7B7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0B +0BFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0B +0BFFFFFFFFFFFFFFDBDBFFFFFFFFFFFFFFDBDBFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBB57539BFFFFFFFFFFFF775377DFFFFFFFFFFFFFFFFF0B +0BFFFFFFFFFFFFFF92006EFFFFFFFFFF6E2592FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF53B7DBDBBB53DFFFFFDF97DBFBBB33FFFFFFFFFFFFFFFF0B +0BFFFFFFFFFFFFFFFF2525FFFFFFFFFF2525DBFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF3397DBFFFFFFDF33DBFF57B7FFFFFF97DBFFFFFFFFFFFFFF0B +0BFFFFFFFFFFFFFFFF9225B7FFFFFFB76E25DBFFFFFFFFFFFFFFFFFFFFFFFFFFDBB7FFFFFFFF7733B7FFFFFFFFFF9B53FF3397FFFFFFFFFFFFFFFFFFFFFFFF0B +0BFFFFFFFFFFFFFFFF92496EFFFFFFB79225DBFFFFB792496EFFFFFFB7926E49FFFFFFFFFFFF2F73FFFFFFFFFFFFDF0FDB5333FFFFFFFFFFFFFFFFFFFFFFFF0B +0BFFFFFFFFFFFFFFDBB7B725FFFFFF929225DBFF9292FFFF00DBFF6EB7FFFF6E92FFFFFFFFFF0F93FFFFFFFFFFFFFF2F979B2F33DFFFFFFFFFFFFFFFFFFFFF0B +0BFFFFFFFFFFFFFFDBB7FF00B7FFDBB7B725DBFF25B7FFFF25B7DB49DBFFFFFFB7FFFFFFFFDF0F97FFFFFFFFFFFFFF3373FFBB330F53FFFFFFFFFFFFFFFFFF0B +0BFFFFFFFFFFFFFFDBDBFF6E49FFB7FFFF00DBFFFFFFFFFF00B74949FFFFFFFFFFFFFFFFFFDF2F97FFFFFFFFFFFFFF3373FFFFFF972F33FFFFFFFFFFFFFFFF0B +0BFFFFFFFFFFFFFFDBDBFFB725FF92FFFF00DBFFFFFFDB9225B7256EFFFFFFFFFFFFFFFFFFFF2F97FFFFFFFFFFFFFF2F73FFFFFFFFBB2F97FFFFFFFFFFFFFF0B +0BFFFFFFFFFFFFFFB7DBFFFF006EB7FFFF00B7FFFFB7DBFF25B7256EFFFFFFFFFFFFFFFFFFFF3373FFFFFFFFFFFFDF2F97FFFFFFFFFF7773FFFFFFFFFFFFFF0B +0BFFFFFFFFFFFFFFB7DBFFFF4925DBFFFF00B7FF6EB7FFFF25B76E49FFFFFFFFFFFFFFFFFFFF9B33FFFFFFFFFFFF5753B7BBFFFFFFFF7773FFFFFFFFFFFFFF0B +0BFFFFFFFFFFFFFF92DBFFFFDB49DBFFFF00B7FF25B7FFB700B7FF25DBFFFFFFFFFFFFFFFFFFFF5377FFFFFFFFBB3397DF53FFFFFFFF57B7FFFFFFFFFFFFFF0B +0BFFFFFFFFFFFFDB2549DBFFFFB7FFDB490049DB254992DB2549DB9225DBFF92FFFFFFFFFFFFFFFF5397FFFFBB53B7FBFF3397FFFF77B7DBFFFFFFFFFFFFFF0B +0BFFFFFFFFFFFFFFB792DBFFFFFFFFFFB7B7B7DBB76EB7FFDB92DBFFB76E6EB7FFFFFFFFFFFFFFFFFFB7737797DBFFFFFFFF977397BBDBFFFFFFFFFFFFFFFF0B +0BFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0B +0BFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0B +0BFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0B +0BFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0B +0BFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0B +0BFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0B +0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B0B +""" + + +BADGES = """ +1010 +000000000000000000ABFE0000000000 +0000000000000000ABFF000000000000 +ABABABABABABABABFFABABABABABABAB +AB7F7F7F7F7F7FFF7F2A2A2A2A2A2AAB +AB7F7F7FF17F7FFF542A2AFF2A2A2AAB +AB7F7F7FF17FABFF2A2A2AFF2A2A2AAB +AB7F7F7F7F7FFF7F2A2A2A2A2A2A2AAB +AB7F7F7F7F7FFF542A2A2A2A2A2A2AAB +AB7F7F7F7F7FFFFFFFFF2A2A2A2A2AAB +AB7F7F7F7F7F7F7F7FFF2A2A2A2A2AAB +AB7F7FFFF17F7F7F7FFF2A2AFFFF2AAB +AB7F7F7F7FF1F1F1F1FFFFFF542A2AAB +AB7F7F7F7F7F7F7F7FFF2A2A2A2A2AAB +ABABABABABABABABABFFABABABABABAB +000000000000000000ABFF0000000000 +00000000000000000000ABFF00000000 +000000000000000000F3FF0000000000 +0000000000000000F3FF000000000000 +F3F3F3F3F3F3F3F3FFF3F3F3F3F3F3F3 +F3AAAAAAAAAAAAFFAA555555555555F3 +F3AAAAAAF4AAAAFF7F5555FF555555F3 +F3AAAAAAF4AAF3FF555555FF555555F3 +F3AAAAAAAAAAFFAA55555555555555F3 +F3AAAAAAAAAAFF7F55555555555555F3 +F3AAAAAAAAAAFFFFFFFF5555555555F3 +F3AAAAAAAAAAAAAAAAFF5555555555F3 +F3AAAAFFF4AAAAAAAAFF5555FFFF55F3 +F3AAAAAAAAF4F4F4F4FFFFFF7F5555F3 +F3AAAAAAAAAAAAAAAAFF5555555555F3 +F3F3F3F3F3F3F3F3F3FFF3F3F3F3F3F3 +000000000000000000F3FF0000000000 +00000000000000000000F3FF00000000 +000000000000000000FFFE0000000000 +0000000000000000FFFF000000000000 +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +000000000000000000FFFF0000000000 +00000000000000000000FFFF00000000 +""" + + +COMPATIBLE_TAG = '\n'.join(COMPATIBLE) + +BOOT_INFO = """ + + +{COMPATIBLE_TAG} + + +MacROM for NewWorld. + + + +{BITMAP} + + + +{BOOT_SCRIPT} + + +{BADGES} + + +""".format(**locals()) + + +BOOT_INFO = '\n'.join(l for l in BOOT_INFO.split('\n') if l) +BOOT_INFO = BOOT_INFO.replace('\n', '\r') +BOOT_INFO += '\r\x04' # CR, EOT +BOOT_INFO = BOOT_INFO.encode('ascii') + +if len(BOOT_INFO) > DATA_OFFSET: + raise ValueError + +# Insert the text +tbxi[:len(BOOT_INFO)] = BOOT_INFO + + + +# Checksum + +cksum = adler32(tbxi) +cksum_str = ('\r\\ h# %08X' % cksum).encode('ascii') + +tbxi.extend(cksum_str) + + + +# Write out. + +with open(out_path, 'wb') as f: + f.write(tbxi) diff --git a/scripts/lzss.py b/scripts/lzss.py new file mode 100644 index 0000000..067796a --- /dev/null +++ b/scripts/lzss.py @@ -0,0 +1,14 @@ +import os.path +import subprocess as sp + +def _run(arg, input): + lzbin = os.path.join(os.path.dirname(__file__), 'lzss') + p = sp.Popen([lzbin, arg], stdin=sp.PIPE, stdout=sp.PIPE, bufsize=0x400000) + output, stderr = p.communicate(input) + return output + +def compress(data): + return _run('c', data) + +def extract(data): + return _run('x', data) diff --git a/scripts/prclmake.py b/scripts/prclmake.py new file mode 100755 index 0000000..b52642a --- /dev/null +++ b/scripts/prclmake.py @@ -0,0 +1,83 @@ +#!/usr/bin/env python3 + +from prcltool import ParcelsArea, ParcelStruct, ParcelEntry +import argparse +from sys import argv + + +class DataLoader(argparse.Action): + def __call__(self, parser, namespace, values, option_string=None): + path = values[0] + + try: + p2 = path + '.patch' + with open(p2, 'rb') as f: + namespace.bytes = f.read() + print('Using', p2) + except FileNotFoundError: + with open(path, 'rb') as f: + namespace.bytes = f.read() + +class DataReader(argparse.Action): + def __call__(self, parser, namespace, values, option_string=None): + d = b''.join(s.encode('ascii')+b'\0' for s in values) + namespace.bytes = d + namespace.should_checksum = False + +def hex(s): + return int(s, 16) + +def fourcc(s): + b = s.encode('ascii') + if len(b) != 4: + raise ValueError('type code not four bytes') + return b + +p1 = argparse.ArgumentParser() +p2 = argparse.ArgumentParser() + +p1.add_argument('--flags', '-f', action='store', type=hex, default=0) +p1.add_argument('--fourcc', '-t', action='store', type=fourcc, default=' ') +p1.add_argument('--name', '-n', action='store', default='') +p1.add_argument('--compat', '-c', action='store', default='') + +p2.add_argument('--fourcc', '-t', action='store', type=fourcc, default=' ') +p2.add_argument('--flags', '-f', action='store', type=hex, default=0) +p2.add_argument('--lzss', '-l', action='store_true', dest='compress') +p2.add_argument('--name', '-n', action='store', default='') +p2.add_argument('--backref', action='store_true', dest='backref_allowed') +p2.add_argument('--nosum', action='store_false', dest='should_checksum') +p2.add_argument('--src', '-s', nargs=1, dest='bytes', action=DataLoader) +p2.add_argument('--data', '-d', nargs='+', dest='bytes', action=DataReader) + + +# Usage: prog.py [ --prcl prcl-opts [ --bin bin-opts ] ... ] ... + +progname, dest, *args = argv + +groups = [] + +me = ParcelsArea() + +for a in args: + if a in ('--prcl', '--bin'): + n = [] + groups.append(n) + n.append(a) + +for g in groups: + t, *opts = g + + if t == '--prcl': + prcl = ParcelStruct() + p1.parse_args(args=opts, namespace=prcl) + me.prcls.append(prcl) + elif t == '--bin': + bn = ParcelEntry() + p2.parse_args(args=opts, namespace=bn) + prcl.entries.append(bn) + else: + raise ValueError('bad arg') + +with open(dest, 'wb') as f: + f.write(bytes(me)) diff --git a/scripts/prcltool.py b/scripts/prcltool.py new file mode 100644 index 0000000..d91fb2f --- /dev/null +++ b/scripts/prcltool.py @@ -0,0 +1,189 @@ +# Ripped from somewhere else. +# Can kind-of rip parcels. +# Needs neatening up. + +import struct +from binascii import crc32 +import lzss +import struct + +class ParcelsArea: + MAGIC = b'prcl \x01\x00\x00\x00 \x00\x00\x00\x14 \x00\x00\x00\x14 \x00\x00\x00\x00'.replace(b' ', b'') + + def __init__(self, bytes=None): + if bytes is not None: + if not bytes.startswith(self.MAGIC): + raise ValueError('Instead of a prcl magic number: %r' % bytes[:len(self.MAGIC)]) + + # Read all the structs in the prcl area! + prcls = ParcelStruct.scan(bytes=bytes, first_offset=len(self.MAGIC)) + prcls = list(prcls) + self.prcls = prcls + + for prcl in prcls: + for entry in prcl.entries: + tpl = (entry.load_offset, entry.load_len, entry.compress) + + x = bytes[entry.load_offset : entry.load_offset+entry.load_len] + if entry.compress: + x = lzss.extract(x) + entry.bytes = x + + else: + self.prcls = [] + + def __bytes__(self): + binaries_added = {} # (bytes, compress): (compressed_bytes, offset, cksum) + things = bytearray(self.MAGIC) + + for prcl in self.prcls: + prcl_offset = len(things) + things.extend(bytes(len(prcl))) + + for entry in prcl.entries: + dict_lookup = (entry.bytes, entry.compress) + + try: + if not entry.backref_allowed: raise ValueError + final_bytes, bytes_offset, cksum = binaries_added[dict_lookup] + + except: + # Need to use this binary! + final_bytes = entry.bytes + if entry.compress: + final_bytes = lzss.compress(final_bytes) + + bytes_offset = len(things) + cksum = crc32(final_bytes) + + things.extend(final_bytes) + + binaries_added[dict_lookup] = final_bytes, bytes_offset, cksum + + # Pad to 4-byte boundary. Apple's build tool left pad bytes uninitialised! + while len(things) % 4: + things.append(0x99) + + # Tell this structure where it can find its binary data. + entry.uncompressed_len = len(entry.bytes) + entry.save_cksum = cksum if entry.should_checksum else 0 + entry.save_offset = bytes_offset + entry.save_len = len(final_bytes) + + # Then tell it where it can find the next one, if any + if prcl is self.prcls[-1]: + prcl.save_nextoffset = 0 + else: + prcl.save_nextoffset = len(things) + + things[prcl_offset:prcl_offset+len(prcl)] = bytes(prcl) + + # So now all structs and all data are placed. Phew. + return bytes(things) + + +class ParcelStruct: + HEADER_FMT = '>I4s4I32s32s' + + @classmethod + def scan(cls, bytes, first_offset): + offset = first_offset + + while offset: + parcel = cls(bytes=bytes, offset=offset) + yield parcel + offset = parcel.load_nextoffset + + def __init__(self, bytes=None, offset=None): + if bytes is not None: + load_nextoffset, fourcc, my_len, flags, entry_count, entry_len, name, compat = struct.unpack_from(self.HEADER_FMT, bytes, offset) + + # Checks + # if entry_len != ParcelEntry.__len__(): + # raise ValueError('Parcel entry of %d bytes, expected %d' % (entry_len, ParcelEntry.__len__())) + + # if my_len != header_size + entry_count*entry_len: + # raise ValueError('Incorrect parcel header size field %d not %d' % (my_len, struct.calcsize(self.HEADER_FMT) + entry_count*entry_len)) + + # Semantics + self.fourcc = fourcc + self.name = name.rstrip(b'\0').decode('ascii') + self.compat = compat.rstrip(b'\0').decode('ascii') + self.flags = flags + + len_of_entries = entry_count*entry_len + entry_offsets = range(offset + my_len - len_of_entries, offset + my_len, entry_len) + self.entries = [ParcelEntry(bytes[o : o+entry_len]) for o in entry_offsets] + + # Ephemerides + self.load_nextoffset = load_nextoffset + + else: + self.fourcc = b' ' + self.name = '' + self.compat = '' + self.flags = 0 + + self.entries = [] + + def __len__(self): + return struct.calcsize(self.HEADER_FMT) + sum(len(e) for e in self.entries) + + def __bytes__(self): + save_nextoffset = self.save_nextoffset + fourcc = self.fourcc + my_len = len(self) + flags = self.flags + entry_count = len(self.entries) + entry_len = ParcelEntry.__len__() + name = self.name.encode('ascii') + compat = self.compat.encode('ascii') + + header = struct.pack(self.HEADER_FMT, save_nextoffset, fourcc, my_len, flags, entry_count, entry_len, name, compat) + + entries = b''.join(bytes(e) for e in self.entries) + + return header + entries + +class ParcelEntry: + FMT = '>4sI4s4I32s' + + def __init__(self, bytes=None): + if bytes is not None: + (fourcc, flags, compress, uncompressed_len, load_cksum, load_len, load_offset, name) = struct.unpack(self.FMT, bytes) + + self.fourcc = fourcc + self.flags = flags + self.compress = (compress == b'lzss') + self.uncompressed_len = uncompressed_len + self.name = name.rstrip(b'\0').decode('ascii') + self.backref_allowed = False + self.should_checksum = True + + # Ephemeral stuff + self.load_cksum = load_cksum + self.load_len = load_len + self.load_offset = load_offset + + #else: + # self.fourcc = b' ' + # self.flags = 0 + # self.compress = False + # self.uncompressed_len = 0 + # self.name = '' + + def __bytes__(self): + fourcc = self.fourcc + flags = self.flags + compress = b'lzss' if self.compress else b'\0\0\0\0' + uncompressed_len = self.uncompressed_len + save_cksum = self.save_cksum + save_len = self.save_len + save_offset = self.save_offset + name = self.name.encode('ascii') + + return struct.pack(self.FMT, fourcc, flags, compress, uncompressed_len, save_cksum, save_len, save_offset, name) + + @classmethod + def __len__(cls): + return struct.calcsize(cls.FMT) diff --git a/trampoline.elf b/trampoline.elf new file mode 100644 index 0000000..b1713e5 Binary files /dev/null and b/trampoline.elf differ