From 4ecebdd842a319b516a7efee76b3f8bab796f161 Mon Sep 17 00:00:00 2001 From: matsutsuka Date: Wed, 2 Jul 2008 07:17:14 +0000 Subject: [PATCH] A binary conversion tool has been modified to support variations. --- platform/pc-6001/Makefile.pc-6001 | 19 +- tools/z80/hex2bin/.cvsignore | 1 + tools/z80/hex2bin/Makefile | 17 ++ tools/z80/hex2bin/README.txt | 131 +++++++++++++ tools/z80/hex2bin/mode1 | Bin 0 -> 30 bytes tools/z80/hex2bin/mode2 | Bin 0 -> 30 bytes tools/z80/hex2bin/mode5 | Bin 0 -> 30 bytes tools/z80/hex2bin/n88 | Bin 0 -> 271 bytes tools/z80/hex2bin/rom60 | 1 + tools/z80/hex2bin/rom62 | 1 + tools/z80/hex2bin/src/hexameter.c | 315 ++++++++++++++++++++++++++++++ tools/z80/hex2bin/src/ihx2bin.c | 190 ++++++++++++++++++ tools/z80/hex2bin/src/ihx2bin.h | 47 +++++ tools/z80/hex2bin/suffix | Bin 0 -> 12 bytes tools/z80/hex2cas/hex2cas.exe | Bin 15892 -> 0 bytes 15 files changed, 714 insertions(+), 8 deletions(-) create mode 100644 tools/z80/hex2bin/.cvsignore create mode 100644 tools/z80/hex2bin/Makefile create mode 100644 tools/z80/hex2bin/README.txt create mode 100644 tools/z80/hex2bin/mode1 create mode 100644 tools/z80/hex2bin/mode2 create mode 100644 tools/z80/hex2bin/mode5 create mode 100644 tools/z80/hex2bin/n88 create mode 100644 tools/z80/hex2bin/rom60 create mode 100644 tools/z80/hex2bin/rom62 create mode 100644 tools/z80/hex2bin/src/hexameter.c create mode 100644 tools/z80/hex2bin/src/ihx2bin.c create mode 100644 tools/z80/hex2bin/src/ihx2bin.h create mode 100644 tools/z80/hex2bin/suffix delete mode 100644 tools/z80/hex2cas/hex2cas.exe diff --git a/platform/pc-6001/Makefile.pc-6001 b/platform/pc-6001/Makefile.pc-6001 index 7784ade8c..01d41ce89 100644 --- a/platform/pc-6001/Makefile.pc-6001 +++ b/platform/pc-6001/Makefile.pc-6001 @@ -2,7 +2,7 @@ # Makefile for PC-6001 using z80/SDCC # @author Takahide Matsutsuka # -# $Id: Makefile.pc-6001,v 1.7 2007/11/28 10:11:55 matsutsuka Exp $ +# $Id: Makefile.pc-6001,v 1.8 2008/07/02 07:17:14 matsutsuka Exp $ # ifndef CONTIKI @@ -48,7 +48,7 @@ endif ### setup default values ifndef HEX2BIN - HEX2BIN = hex2cas + HEX2BIN = ../../tools/z80/hexameter/hexameter endif ### setup flags to be used in compiler, assembler, and HEX2BIN @@ -59,16 +59,16 @@ CFLAGS += -DMEMORY_$(MEMORY) -DARCH_$(ARCH) -DCTK_$(CTKCONF) ifeq ($(MEMORY),16K) LDFLAGS += --code-loc 0xc40f --data-loc 0 - HEX2BINFLAGS = -1 -n contki -o contiki.p6 + HEX2BINFLAGS = -p mode1 -s suffix -n contki -o contiki.p6 else ifeq ($(MEMORY),ROM) LDFLAGS += --code-loc 0x4004 --data-loc 0xf000 - HEX2BINFLAGS = -r -o contiki.rom + HEX2BINFLAGS = -p rom60 -o contiki.rom else ifeq ($(ARCH),PC6001MK2) LDFLAGS += --code-loc 0x800f --data-loc 0 - HEX2BINFLAGS = -5 -o contiki2.p6 + HEX2BINFLAGS = -p mode5 -s suffix -o contiki2.p6 else LDFLAGS += --code-loc 0x840f --data-loc 0 - HEX2BINFLAGS = -2 -n contki -o contiki.p6 + HEX2BINFLAGS = -p mode2 -s suffix -n contki -o contiki.p6 endif ifeq ($(LOADER),1) @@ -107,10 +107,13 @@ contiki: contiki.p6 .SUFFIXES: -%.p6: %.ihx +%.p6: $(HEX2BIN) %.ihx $(HEX2BIN) $(HEX2BINFLAGS) $< %.rom: %.ihx - $(HEX2BIN) $(HEX2BINFLAGS) $< + $(HEX2BIN) $(HEX2BIN) $(HEX2BINFLAGS) $< + +$(HEX2BIN): + cd ../../tools/z80/hexameter/; make remove-ctk: rm -f obj_$(TARGET)/ctk*; diff --git a/tools/z80/hex2bin/.cvsignore b/tools/z80/hex2bin/.cvsignore new file mode 100644 index 000000000..15c9185a1 --- /dev/null +++ b/tools/z80/hex2bin/.cvsignore @@ -0,0 +1 @@ +hexameter.exe diff --git a/tools/z80/hex2bin/Makefile b/tools/z80/hex2bin/Makefile new file mode 100644 index 000000000..2a24ab429 --- /dev/null +++ b/tools/z80/hex2bin/Makefile @@ -0,0 +1,17 @@ +# +# Makefile for hexameter +# @author Takahide Matsutsuka +# +# $Id: Makefile,v 1.1 2008/07/02 07:17:14 matsutsuka Exp $ +# + +CFLAGS = +SOURCEDIR = src +TARGET = hexameter.o ihx2bin.o + +vpath %.c $(SOURCEDIR) + +hexameter: $(TARGET) + +clean: + rm -f *.o *~ hexameter.exe diff --git a/tools/z80/hex2bin/README.txt b/tools/z80/hex2bin/README.txt new file mode 100644 index 000000000..f0bc92907 --- /dev/null +++ b/tools/z80/hex2bin/README.txt @@ -0,0 +1,131 @@ +hexameter : Convert Intel hex files to a binary file +version 2.0.0 + Copyright (c) 2003-2008, Takahide Matsutsuka. + +1/ What is it? + +It converts Intel hex files, which emitted by SDCC-Z80 compiler, to +a binary file. You can attach additional prefix and/or suffix file +to comply the file with arbitrary binary format. +It provides a development environment of C language on PC-6001 and +other old computers. + + +2/ Installation + +Installation can be done in following steps. + +a) Download and install SDCC from http://sdcc.sf.net/ + Version 2.8.0 is tested. + SDCC is a cross-compiler for Z80 and other 8bit CPUs. + Extract an archive on your disk, say "c:/sdcc". + +b) Copy hexameter.exe to any path-available directory. for exmaple + "c:/sdcc/bin". + + +3/ Use + +a) Write your own C code. + +b) Compile your code using SDCC. + While linking, you need to specify options for SDCC so that the + code can be worked on your machine. + See sample/Makefile for actual usage. + + % sdcc -mz80 -c YOUR_CODE1.c + % sdcc -mz80 -c YOUR_CODE2.c + + This step creates a file YOUR_CODE1.o and YOUR_CODE2.o respectively, + which run on Z80-based machine. + + % for target in YOUR_CODE1.o YOUR_CODE2.o; do echo $@ >> YOUR_LIB.lib $@; done + + This step makes a library file. + + sdcc -mz80 --no-std-crt0 --code-loc 0x840f --data-loc 0 -o YOUR_APP.ihx crt0.o -lYOUR_LIB.lib + + -mz80 specifies the Z80 mode. + --code-loc specifies the start address of your object code. + Basically, it depends on the machine and RAM size. As for PC-6001, + 0x840f for 32kB, or 0xc40f for 16kB. As for PC-6001mkII, it would + be 0x800f. + If you are not sure what you are about to do, just leave it as + default 0x840f. + --data-loc 0 specifies the code is followed by data. + You can specify an arbitrary address instead. + --no-std-crt0 indicates that you use your own crt0 instead of sdcc's + default crt0 object. The customized crt0.o file is in lib directory + of this release. + +c) Convert ihx file to cas file using hex2cas. + + hexameter YOUR_CODE.ihx [YOUR_CODE2.ihx ...] + The ihx files are just attached in the specified order. + + Here you can take some options: + -p specify prefix file name. + -s specify suffix file name. + -n specify PC-6001 cassette file name, + must be 6 characters or less. + -v verbose output + -o specify output file name + -b size of the output file in hexadecimal bytes. + only if the size of the output is less than the size + specified, the trailing bytes will filled by zeroes. + note that it doesn't mean the size of output is + restricted by the given size. + -h displays simple usage + + Prefixes and suffixes are provided by files, which should be in the same + directory as hexameter.exe. + mode1 + mode2 + mode5 + n88 + rom60 + rom62 + suffix + +d) Example + + The following is a typical example to convert from ihx files to + PC-6001 loadable cassette format. + % hexameter -p mode2 -s suffix mycode1.ihx mycode2.ihx -o myapp.p6 + +e) Load your cas file into your 6001 emulator. + + I've checked it working on the following emulators: + + VirtualTrek + http://www.geocities.com/emucompboy/ + iP6Win + http://www.retropc.net/mm/pc6001/ + PC-6001VW + http://bernie.hp.infoseek.co.jp/develop/pc6001vw.html + + +4/ Note + +- While I've tested the tool on Cigwin on Win32, I think it works + on other environments with a little work. + +- SDCC has many isuues regarding compilation. Don't blame me about them! :) + + +5/ History + +3/29/2003 1.0.0 First version +4/20/2003 1.0.1 Mode option has been added +9/01/2007 1.1.0 ROM-mode has been added +9/28/2007 1.2.0 Customized crt0 has been introduced to clear global data +3/15/2008 1.3.0 VRAM options introduced +4/28/2008 1.4.0 Header file option introduced + +5/17/2008 2.0.0 Migrated to hexameter, to support more flexible configurations + + +Enjoy! + +http://www.markn.org/ +markn@markn.org diff --git a/tools/z80/hex2bin/mode1 b/tools/z80/hex2bin/mode1 new file mode 100644 index 0000000000000000000000000000000000000000..6124f2d1f24773bffaaf103ae8ecc99c1f687634 GIT binary patch literal 30 fcmcb783u|Ia|?1(d5>^0ELHPxHZgExU|;|M7>x~_ literal 0 HcmV?d00001 diff --git a/tools/z80/hex2bin/mode2 b/tools/z80/hex2bin/mode2 new file mode 100644 index 0000000000000000000000000000000000000000..797cd18aeef7df7fa52fda8b2756a67c4187706c GIT binary patch literal 30 acmcb783q`@fVYK +#else +#include +#endif +#include +#include +#ifndef TRUE +#define TRUE 1 +#endif + +#include "ihx2bin.h" + +#define MAXFILES 256 + +struct Configuration { + char* output; + char* prefix; + char* suffix; + char* dir; + char archname[6]; + char *files[MAXFILES]; + unsigned char verbose; + // number of the ihx files + int length; + // output file size + int size; + // output file wriiten size + int written; +}; + +static char *changeExt(const char *path, const char* ext) { + char *p; + char *tail; + char *changed; + int len; + int extlen = strlen(ext); + + for (tail = (char*) path; *tail != 0; tail++); + for (p = tail; p > path; p--) { + + if (*p == '.') { + len = p - path; + changed = (char*) malloc(len + extlen + 2); + + strncpy(changed, path, len + 1); + strcpy(changed + len + 1, ext); + return changed; + } + } + + len = strlen(path); + changed = (char*) malloc(len + extlen + 2); + strncpy(changed, path, len); + *(changed + len) = '.'; + strcpy(changed + len + 1, ext); + return changed; +} + +static unsigned char analyzeOption(int argc, char **argv, struct Configuration *config) { + int c; + opterr = 0; + while ((c = getopt(argc, argv, "hvo:p:s:n:b:")) != EOF) { + int i; + switch (c) { + case 'v': + config->verbose = TRUE; + break; + case 'o': + config->output = optarg; + break; + case 'p': + config->prefix = optarg; + break; + case 's': + config->suffix = optarg; + break; + case 'b': + sscanf(optarg, "%x", &config->size); + break; +// case 'n': +// for (i = 0; i < 6; i++) { +// if (optarg[i] == 0) { +// break; +// } +// config->archname[i] = optarg[i]; +// } +// break; + case 'h': + printf("%s : Convert Intel HEX file (ihx) to binary file, ver. 2.0.0\n", getprogname()); + printf("Copyright (c) 2003-2008 Takahide Matsutsuka \n"); + printf("Usage: %s [options] [...]\n", argv[0]); + printf("Options:\n"); + printf(" -v verbose output\n"); + printf(" -o \n"); +// printf(" -n (for NEC PC series)\n"); + printf(" -p \n"); + printf(" -s \n"); + printf(" -b \n"); + printf(" -h print this help\n"); + + return 1; + default: + printf("unknown option:%c\n", optopt); + return 1; + } + } + + return 0; +} + +static int isFileExists(const char *dir, const char *filename) { + char path[MAX_PATH]; + FILE *f; + + if (!filename) { + return 0; + } + if (dir) { + strcpy(path, dir); + strcpy(path + strlen(path), filename); + } else { + strcpy(path, filename); + } + if (!(f = fopen(path, "rb"))) { + printf("cannot open: %s\n", filename); + return 1; + } + fclose(f); + + return 0; +} + + +static int checkExistence(struct Configuration *config) { + int i; + int r; + FILE *f; + fclose(f); + if (r = isFileExists(config->dir, config->prefix)) { + return r; + } + if (r = isFileExists(config->dir, config->suffix)) { + return r; + } + for (i = 0; i < config->length; i++) { + f = fopen(config->files[i], "r"); + if (!f) { + printf("cannot open: %s\n", config->files[i]); + return 1; + } + fclose(f); + } + return 0; +} + +/** + * @return writtn size in bytes + */ +static +int copy(FILE *out, const char* dir, const char* filename, unsigned char verbose) { + FILE *in; + char ch; + char path[MAX_PATH]; + int bytes = 0; + if (!filename) { + return 0; + } + if (dir) { + strcpy(path, dir); + strcpy(path + strlen(path), filename); + } else { + strcpy(path, filename); + } + if (verbose) { + printf("importing file: %s\n", path); + } + in = fopen(path, "rb"); + while ((ch = getc(in)) != EOF) { + putc(ch, out); + bytes++; + } + return bytes; +} + +static int output(struct Configuration *config) { + FILE *out; + int i; + // TODO: ARCH FILE NAME + + if (!(out = fopen(config->output, "wb"))) { + printf("cannot open output file:%s\n", config->output); + return 1; + } + config->written += copy(out, config->dir, config->prefix, config->verbose); + for (i = 0; i < config->length; i++) { + config->written += ihx2bin(out, config->files[i], config->verbose); + } + config->written += copy(out, config->dir, config->suffix, config->verbose); + + if (config->size) { + if (config->verbose) { + printf("Writing trailing bytes\n"); + } + for (; config->size > config->written; config->written++) { + putc(0, out); + } + } + + fclose(out); + return 0; +} + + +int main(int argc, char **argv) { + struct Configuration config; + unsigned char r; + + memset(&config, 0, sizeof(struct Configuration)); + +#if __CYGWIN32__ + char path[MAX_PATH]; + GetModuleFileName(NULL, path, MAX_PATH); + int len = strlen(path); + while (len > 0) { + if (path[len] == '\\') { + path[len + 1] = 0; + break; + } + len--; + } + config.dir = path; +#endif + + while (optind < argc) { + if (r = analyzeOption(argc, argv, &config)) { + return r; + } + if (optind == argc) { + break; + } + if (config.length == MAXFILES) { + printf("too much files specified\n"); + return 1; + } + config.files[config.length] = argv[optind]; + config.length++; + optind++; + } + + if (config.length == 0) { + printf("no input specified\n"); + return 1; + } + + if (config.output == NULL) { + config.output = changeExt(config.files[0], "bin"); + } + + if (r = checkExistence(&config)) { + return r; + } + if (config.verbose) { + printf("Generating file: %s\n", config.output); + } + if (r = output(&config)) { + return r; + } + + if (config.verbose) { + printf("Done.\n"); + } + return 0; +} diff --git a/tools/z80/hex2bin/src/ihx2bin.c b/tools/z80/hex2bin/src/ihx2bin.c new file mode 100644 index 000000000..3a068e5a8 --- /dev/null +++ b/tools/z80/hex2bin/src/ihx2bin.c @@ -0,0 +1,190 @@ +/* + * Copyright (c) 2003-2008, Takahide Matsutsuka. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. The end-user documentation included with the redistribution, if + * any, must include the following acknowlegement: + * "This product includes software developed by Takahide Matsutsuka." + * Alternately, this acknowlegement may appear in the software itself, + * if and wherever such third-party acknowlegements normally appear. + * 4. The name of the author may not be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * Intel HEX format to PC-6001 CAS format conversion utility. + */ + +#include +#include "ihx2bin.h" + +/** + * Convert a character to a value. + * @param ch a character to convert + * @return integer value represents the given character + */ +static int aton(const unsigned char ch) { + int n; + if (ch >= '0' && ch <= '9') { + return ch - '0'; + } + if (ch >= 'A' && ch <= 'F') { + return ch - 'A' + 10; + } + if (ch >= 'a' && ch <= 'f') { + return ch - 'a' + 10; + } + + return 0; +} + +/** + * Convert a byte characters from a given file and returns a byte. + * @param in file + * @return -1 if EOF + */ +static int getByte(FILE *in) { + int ch1, ch2; + ch1 = getc(in); + if (ch1 == EOF) { + return -1; + } + ch2 = getc(in); + if (ch2 == EOF) { + return -1; + } + return 16 * aton(ch1) + aton(ch2); +} + +/** + * Extract a 64kB memory map from given file. + * IHEX format is as follows: + * :A_B___C_D_....D_E_ + * A_ : size of this chunk + * B___: address (big endian) + * C_ : record type (00: notmal data, 01: end) + * D_....D_: data + * E_ : check sum + * :0DCCCF00673008D620D607D63013C937C904 + * :00000001FF + * @param inFilename file name to convert + * @param start pointer to start address + * @param end pointer to end address + * @return 0 if noerror, otherwise if error + */ +static int ihx2mem(const char *inFilename, unsigned char *buffer, unsigned int *start, unsigned int *end) { + FILE *in; + *start = 0xffff; + *end = 0; + + in = fopen(inFilename, "rb"); + if (in == NULL) { + printf("cannot open input file\n"); + return 1; + } + + while(1) { + int ch; + int length; + unsigned int address; + int tmp; + + // skip checksum and cr/lf + while ((ch = getc(in)) != ':') { + if (ch == EOF) { + break; + } + } + if (ch == EOF) { + break; + } + + // get length of this chunk + length = getByte(in); + if (length <= 0) { + // TODO: end of bytes, retrieve variables + break; + } + + // make an address + tmp = getByte(in); + if (tmp < 0) { + break; + } + address = tmp * 256; + tmp = getByte(in); + if (tmp < 0) { + break; + } + address += tmp; + if (*start > address) { + *start = address; + } + + if (*end < (address + length)) { + *end = address + length; + } + + // ignore record type + if (getByte(in) < 0) { + break; + } + + while (length > 0) { + buffer[address] = getByte(in); + address++; + length--; + } + } + + fclose(in); + return 0; +} + +/** + * @return written size + */ +int ihx2bin(FILE* dst, const char *src, unsigned char verbose) { + unsigned int start, end; + unsigned char buffer[65536]; + unsigned int i; + + memset(buffer, 0, 65536); + + if (ihx2mem(src, buffer, &start, &end)) { + printf("cannot open input file: %s\n", src); + return 0; + } + + if (verbose) { + printf("importing ihx : %s (%04x:%04x)\n", src, start, end); + } + for (i = start; i < end; i++) { + putc(buffer[i], dst); + } + + return (end - start); +} diff --git a/tools/z80/hex2bin/src/ihx2bin.h b/tools/z80/hex2bin/src/ihx2bin.h new file mode 100644 index 000000000..d06c81d13 --- /dev/null +++ b/tools/z80/hex2bin/src/ihx2bin.h @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2003-2007, Takahide Matsutsuka. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * 3. The name of the author may not be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * $Id: ihx2bin.h,v 1.1 2008/07/02 07:17:14 matsutsuka Exp $ + * + */ + +/* + * A header file for ihx2bin + * @author Takahide Matsutsuka + */ + +#ifndef __IHX2BIN_H__ +#define __IHX2BIN_H__ + +/* A default architecture-depend file name. */ +#define DEFAULT_ARCH_FILENAME "noname" + +int ihx2bin(FILE* dst, const char *src, unsigned char verbose); + +#endif /* __IHX2BIN_H__ */ diff --git a/tools/z80/hex2bin/suffix b/tools/z80/hex2bin/suffix new file mode 100644 index 0000000000000000000000000000000000000000..ce58bc9f84b9623e708de4eb8427a57d9f9a160f GIT binary patch literal 12 KcmZQzKmY&$3;+QD literal 0 HcmV?d00001 diff --git a/tools/z80/hex2cas/hex2cas.exe b/tools/z80/hex2cas/hex2cas.exe deleted file mode 100644 index 1770cc9ebb60d470dc0e222310a58021a11022b6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 15892 zcmeHO4{%(?dEb*xAZ!^ai~%)x!XqOk@(dP|d_F6}Bxg&{7_hOhB`}T6(^-0wE|TtU z?hn}10?{*rkHf`NXiFyywF{(f#+|yY>$sG*XYBgOjOn<+rI0eI0*0I_Wh$s96&c0X z-?x9>yZ258lL3-U+0owH{r216_h-M|x9{!KhTq=D${Ax`H$J9618*B$e$f91Na!BAX_#v%i;;E2{642L5LZM&((l3^_r);czB)`7@`awVR(3g<79f{_Sc5BN4Vko~a+%N@tz3Ux z80$d|#x(teal3d2;-wD!YF&uPSf_`b0nTTg8WZM@1cV;0!Vl?1w$dOJB@Naz_5~9` z(8w$X0@=*2KrTuF#w8GXR1xUm7F4kig@-#zqS_+qtAT*1n@VfrWQj$+FO^u{4&PU`fO@+wvfCm zr$gaFVREBvd=L7ee`<85sIeuZ&sHDJQs+CsoYto@`c(SF@wdHzmkq6G@SI3*<4yW> zMxRcdT>Q;#Qg&UgLJO?s2&XQuSoR<`DOI*U$f0zGOOdPVA{^vYtKb;z#W)D_OJYhHdkT>L0 zqj|QoY;rWC=Z}w9ayvQr-#eP`$#m!U>QkN?7+J1Q-N;RQV4q%nu?~(H|+om2mK?X~n9`Nib2V8;e#aL8Mo|O$>y_DMt9l?4ob+S%4Gd0zk(Q6PW z8NF((l_fFIRoB2T6f0@{&D7|dWr>aS``|+Svcy#rPXPf%Z{mLZRwTAgJOV;a&oeE+ z4rusE>*ru_D*J^~>?AK-eTuc`^r`BTaPjY6n0bsd*Pdcc#5~5>PYDre3F zh??cpnY5mt4DHqD5b*otY<~?cZV`XYX(VDk3A;HK=HSdJ)>ta4+Y*Iv;;Ue4s`kLS z&ebeOE~3?@GQfjHD#;g}YA$jvH9A+Q-rayGf$gb$vse^YS3mN<jQ0;}n**#c zeySo$E8FB>iGpYHpeU40{)s45O#Y!LcqjKB7>D!>d$tE%CU#*t$mz4B3YNHv>c@vb zkR0WFV3HLRchQ>BJ^Rp0P3U4b%AluFJ0Z|7!2)?3#rOF#nC7kPrt#r){W?4AFG)tg$kLFTh0=LIM#QHj26J_*wP zqs0HH;>UR80P+G6lOX2wIsCGTgZLS{i6Z5aWR)V)4JdUJ_eAna^m>tceZ%fGnM~cp zy_5VREo^7dEG8M|QNvuJz{BVOaY$Xx62N(&T5Pz<;}(>xuRhAdlx7h@HIZ|8M?ih& z1G+2D(VhXI2seGsUOQ-~a!2~dspFM5(Uv<_^UwrcQ82ocGag{^&`A)_kYvXe#TWl?5dx2 z)#qGw?;TEkUU#)KM?2QzJFy|F$!x2Fe;)pi>fL8yMXudTQPQ0KyQg`r@~3b_uD$9? z)Y7Rj`pxX-E!Xc~5L4$b=64UK9x%M4k!5m=ectfszU6iw|@8OruPJZbM z@Jn5Q0;fFJUaNhP;FdITvZnD%M-5%XAmzV}aZ9)FN=ShgNXLL z?N^);>K zLca77qO9((_L=>`;lv`mu=yix{Jkn{mTU0>V)c9D4PRIa5bgg(VwYoeSiQy@@WNzz zwe#zqV%wQ~PZx=r^p-A~OlbX~VRHcsN5a7olila!h$Is>3uBSCa9eZBiq_a5+ZauR zBH?)30;VmCXse1CH3IrN(ZkxR-e5d#CK4u>Vz)H&SA$x!*3j9$%-_`1d_%K;Xw6dU z)FPT%?55={vT22AT46Pf4Bc`I?-bKEZQMXHr|>v+5N{_#;e?i;7nOtNaC8AnhKItD z`@&j;tKU}NOK%+6qN@VzD&$$2uPrJ!6qQx`Z_@Sg3+R6v=xs%9%_!H$wKlCi628}r zCA3?@33FImr*9EsmxyR`thDykn{Ob0Q{-sijUy7Y=Ej!BCU~NWL+BDJ% z>r6Nz<24>Ndqe#pvu^={InHi2!)7d)2!#i@K5bfkoR8_R`&|50=og@OyD}ZxjkQ+HOu>BCQ6y|0W$%#Kcg#_C2G6PJ7US`@s5}ySVM`v#|s9`3@WFoY{p0>_9&G@ z;XW#7sEj`cl5$ilPDjqoP$SF^>CahtyBc76Tw7C|JfKTjXm1GHD6 zEy93=&WoiI)Ov__<-2W`>G#hJ6X)f zbRJpC_9kc}Y{$EGS5meIKo_?EIpEefxUhzAr^x&n-V2bJOITkdOa!(F=Td^Abe@(x z<(_54;7A`w=YXZN1H!62g_6dlYxB-!rH|ktA8tVpvd~VSls-z1JDJy1Bb5MM{-4s8)ev~}&^n70l@^A_A%WfPWS?rMIA1guLUxNH(3G%cX$2aDt z_@_&d4=ZF3MIA+nojx(o^V9pfmB*CMd|h?P5kjr%RCO>m(5Eb!_GS6685I zj_)xy#b0Chl76l!K|W~n$eHW4^$`@`lO@Ovb}xynl_2l3c_i}dZXDmBo8mucOP9#> ztnc*3b0x^c;FuS_eI>|CtX^nh&m#vo@`vBi1P|TOXg^m=U9I%Xt*f|YyOLVR_F;*0 zS~_UytnO$h(bs8dmz(16v%MjGxW5E>O9}E3H;%8vP4UxduXE-eEIcZ37om^f`SkT!0B`kNgg%1j)7R%3=o7sNeFV>^ ztB;C}F|H3}sU6zNzLLnyVqBfGsnbpI(>m>3qxRXzMc=&woMg!_SFMP$q`z1qeX)%! z?~KotNDtV(|QZvbANYHC$PN7I*rj=8n9} zv@C`I?n4iiT&t*DC2Ew0^Sxb>{@HKg&|2zD>KUK*Y!~v6ijDoBo$bDZP*d1GkIvHe z+K;wwsj8|E*uSrez=E<@c}8a!&}ASm=92J2bP z|LZ_dz6*-lSqaKNgK`FJG|E7hudB!SlY&D2SHh{GF9ei6|3wt06;bH!N*35W8VRtZ z)BCz!5X4iYLT+*JpqX`mqTb|CBV)Ih@Z1B6TE_%W43`=33M;7B1EQhGtMshn^!#5E zk7bu(hVKo|rznrrgGW8*3Rx|@SD*-IHBl_PNXA{DsGXI@bOxRId5pKw%r5bBC8Ad<-6AcSky$I(j z;HcRxq%Wm_N3utG6)1-tlv{}h>~c)yF_31-qW;^!^SYzg5Gd-|Q^>lXDB!W@*W;+F zeJ}aY4EIq)SusY)&w%Hg1Njgr>VAq|^2kd(vC>#jIt8BM)kYkj?Xx|m4zScSBXG!H z*he`$b{05qf@=HcEl^%|P^LklV72YKjMyDkTmuS*wTNda@gNRuZh0XU@Z28H(Y)FAxx`zUU4%!21ZIqBdz1mOpvFA{o~+Fy zk1_XK<4!VmfyZ7Yi1G~ef@(q^TIcB?RJ?0a$Vb344qjX5mq2m)`3InMSzi4SYQ|lm z@CKZ9v~TL#j1$;IGD-pKtVd%e4v&neANMX%gk1xP!D33ZwY8*`NaEnh5FH45$LhYm z7@Zj#y@SEGjf{*$!T|vHMT}_NOyUwV z>D1aVqGo7$tKY!C=_NuVrXb^#D`w$Ac`|Leo6zDWG`k6;1`f*&<$0{Ho4RlBx@CiI zbZ*wWJ2o1d^z|FtjrF%|?!p3r=3=F{!>0y42_PikV!_bSwQ-ZpA09!UqT_hf62ozu z|H4P_wqoRic<6r9i1bs(-XZR-kdWtWzyO%Bdrhv%Nbp;c7{+OPd}lmiju`U07ik96 z-7#$I0mFzAa!>|`;)x+{v}hBnq~ShN5BR{ty~uY!hJi<+Vw?+mRKLB0tD}q&cCD45thS>vM{aiXR>=N~?B9sF2rGi!ipgq;AKV`rO07 zhit`Oa$p8yy@Ph6(6yOwpF+~B@OYn$Y2KhbDfbz;n_~p#^MbtjNyn?NFQ^+uoy*hQ zZ|W-!d#se_G5_X`Dd$w;AaZ9VG33W7_VnNZR6GfUBNIhYV^0X0&m2@P=yr`hB#||_ z!BGO~BO9y9^(l><+iDCsw2DvX`WlOjD3Fg_0IUytlnV6xqWmnPws>X_M}mF$fTw>r zI1smER^E;bobzM6heO+k@b!;5yu8H-5*D8wwquI%L|dsGIeEl%lNI{V=ffs|n(hwy X_!No0