#include #include #include #include #include #include #include #include "DiskImage.h" #include "file_io.h" #define ERR_OPEN "Error: can't open source file" #define ERR_GETLEN "Error: can't get file length!" #define ERR_NOMEM "Error: no memory!" #define ERR_FORMAT "Error: incorrect format" #define ERR_FILEVER "Error: unknown version of" #define ERR_FILECRC "Error: bad file CRC" #define ERR_CANTWRITE "Error: write to file failed!" #define ERR_UNKFORMAT "Error: Unknown format of source file!" #define ERR_MANYCYLS "Error: out of 256 cylinders in opening source file!" #define ERR_MANYSIDS "Error: out of 2 surfaces in opening source file!" #define ERR_IMPOSSIBLE "Error: impossible format in opening source file!" #define ERR_CORRUPT "Error: source file is corrupted!" #define ERR_TD0DOSALLOC "Error: files TD0 in 'DOS Allocated sectors were copied' format not supported!" #define STR_CREATEDISKNAME "MiSTer " char errsect[] = "ERROR: THIS SECTOR NOT FOUND OR IN NON TR-DOS FORMAT!"; static const unsigned char sbootimage[] = { 0x00, 0x01, 0x1a, 0x00, 0xf9, 0xc0, 0xb0, 0x22, 0x31, 0x35, 0x36, 0x31, 0x39, 0x22, 0x3a, 0xea, 0x3a, 0xf7, 0x22, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x22, 0x20, 0x0d, 0x00, 0x02, 0x0f, 0x00, 0xf9, 0xc0, 0xb0, 0x22, 0x31, 0x35, 0x36, 0x31, 0x39, 0x22, 0x3a, 0xea, 0x3a, 0xf7, 0x0d, 0x00, 0x03, 0x0b, 0x00, 0xf9, 0xc0, 0xb0, 0x22, 0x31, 0x35, 0x36, 0x31, 0x36, 0x22, 0x0d, 0x00, 0x04, 0x47, 0x00, 0xea, 0x21, 0xa8, 0x61, 0x11, 0xa9, 0x61, 0x01, 0x07, 0x9d, 0x36, 0x00, 0xed, 0xb0, 0x21, 0xa8, 0x61, 0xed, 0x5b, 0xf4, 0x5c, 0x01, 0x05, 0x0f, 0xcd, 0x13, 0x3d, 0x21, 0x00, 0xa6, 0xed, 0x5b, 0xf4, 0x5c, 0x01, 0x05, 0x08, 0xcd, 0x13, 0x3d, 0x21, 0x50, 0xeb, 0xed, 0x5b, 0xf4, 0x5c, 0x01, 0x05, 0x0d, 0xcd, 0x13, 0x3d, 0xcd, 0xa8, 0x61, 0x21, 0xa8, 0x61, 0x11, 0xa9, 0x61, 0x01, 0x07, 0x9d, 0x36, 0x00, 0xed, 0xb0, 0xc9, 0x0d, 0x00, 0x0a, 0x25, 0x00, 0xe7, 0xc3, 0xa7, 0x3a, 0xda, 0xc3, 0xa7, 0x3a, 0xd9, 0xb0, 0x22, 0x37, 0x22, 0x3a, 0xfd, 0xb0, 0x22, 0x36, 0x35, 0x33, 0x34, 0x37, 0x22, 0x3a, 0xf9, 0xc0, 0xb0, 0x22, 0x32, 0x33, 0x39, 0x33, 0x36, 0x22, 0x3a, 0xf7, 0x0d, 0x80, 0xaa, 0x0a, 0x00, 0x6f, 0x6f, 0x74, 0x31, 0x31, 0x22, 0xca, 0x31, 0x30, 0x0d, 0x80, 0x31, 0x35, 0x36, 0x31, 0x36, 0x0e, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x0d, 0x80, 0xca, 0xf3, 0x5e, 0x06, 0x00, 0x00, 0x00, 0xf3, 0x5e, 0x06, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfd, 0x22, 0xc8, 0xaf, 0xd9, 0x22, 0xca, 0xaf, 0xed, 0x73, 0xcc, 0xaf, 0xed, 0x57, 0x32, 0xce, 0xaf, 0x11, 0x00, 0x00, 0x21, 0x00, 0x9d, 0x01, 0x05, 0x08, 0xcd, 0x13, 0x3d, 0x31, 0x68, 0xbf, 0xf3, 0x21, 0x00, 0xfd, 0x11, 0x01, 0xfd, 0x01, 0x00, 0x01, 0x36, 0xfc, 0xed, 0xb0, 0x21, 0x5a, 0x67, 0x22, 0xfd, 0xfc, 0x3e, 0xc3, 0x32, 0xfc, 0xfc, 0xed, 0x5e, 0x3e, 0xfd, 0xed, 0x47, 0xcd, 0x53, 0xeb, 0xcd, 0x50, 0xeb, 0xcd, 0x13, 0x65, 0xfb, 0x21, 0x9b, 0x6e, 0x11, 0x00, 0x77, 0x01, 0xc8, 0x00, 0xed, 0xb0, 0x21, 0x77, 0x6b, 0x11, 0x00, 0x76, 0x0e, 0x28, 0xed, 0xb0, 0x21, 0x9f, 0x6b, 0x11, 0x5c, 0x76, 0x0e, 0x09, 0xed, 0xb0, 0x11, 0x00, 0x78, 0x3e, 0x40, 0x32, 0x8e, 0x76, 0xcd, 0xf4, 0x62, 0x21, 0x00, 0x78, 0x11, 0x00, 0x81, 0x06, 0x08, 0xc5, 0xcd, 0xd9, 0x63, 0x24, 0x14, 0xc1, 0x10, 0xf7, 0x21, 0x00, 0x77, 0xcd, 0x25, 0x64, 0xcd, 0x25, 0x64, 0xcd, 0x25, 0x64, 0x11, 0x00, 0x8a, 0x3e, 0x80, 0x32, 0x8e, 0x76, 0xcd, 0xf4, 0x62, 0x21, 0x00, 0x8a, 0x11, 0x00, 0x93, 0x06, 0x08, 0xc5, 0xcd, 0xd9, 0x63, 0x24, 0x14, 0xc1, 0x10, 0xf7, 0x06, 0x11, 0x21, 0x00, 0x8a, 0xc5, 0xcd, 0x25, 0x64, 0x24, 0xc1, 0x10, 0xf8, 0xcd, 0xc9, 0x6d, 0x3e, 0xff, 0x32, 0xb0, 0xb3, 0x3c, 0x32, 0xb1, 0xb3, 0x3e, 0x05, 0x32, 0xb2, 0xb3, 0x3e, 0x08, 0x32, 0xb3, 0xb3, 0x3e, 0x0e, 0x32, 0xb4, 0xb3, 0xcd, 0x61, 0x64, 0x3a, 0xb0, 0xb3, 0x3c, 0x32, 0xb0, 0xb3, 0x3a, 0xb0, 0xb3, 0xe6, 0x01, 0xfe, 0x01, 0x20, 0x18, 0x21, 0x84, 0xac, 0x22, 0x87, 0x64, 0xcd, 0x85, 0x64, 0xcd, 0x85, 0x64, 0x21, 0xfc, 0xac, 0x22, 0x87, 0x64, 0xcd, 0x85, 0x64, 0xcd, 0x85, 0x64, 0x3a, 0xb0, 0xb3, 0xe6, 0x03, 0xfe, 0x03, 0x20, 0x21, 0x21, 0x00, 0x40, 0x11, 0x00, 0x78, 0x01, 0xb1, 0xb3, 0xcd, 0xdd, 0x64, 0x21, 0x1b, 0x40, 0x11, 0x00, 0x8a, 0x01, 0xb2, 0xb3, 0xcd, 0xdd, 0x64, 0x21, 0x74, 0xad, 0x22, 0x87, 0x64, 0xcd, 0x85, 0x64, 0x3a, 0xb0, 0xb3, 0xe6, 0x07, 0xfe, 0x07, 0x20, 0xa5, 0x21, 0x60, 0x50, 0x11, 0x00, 0x8a, 0x01, 0xb3, 0xb3, 0xcd, 0xdd, 0x64, 0x21, 0x7b, 0x50, 0x11, 0x00, 0x78, 0x01, 0xb4, 0xb3, 0xcd, 0xdd, 0x64, 0x18, 0x8b, 0xfd, 0x21, 0x5c, 0x76, 0x0e, 0x08, 0x21, 0x00, 0x77, 0x06, 0x28, 0xdd, 0x21, 0x00, 0x76, 0xcd, 0x3e, 0x63, 0xc5, 0x06, 0x05, 0xdd, 0x7e, 0x00, 0xe6, 0x3f, 0xcd, 0x57, 0x63, 0xdd, 0x2c, 0x10, 0xf4, 0x0d, 0x20, 0xef, 0xc1, 0xcd, 0x67, 0x63, 0x10, 0xe1, 0x14, 0x1e, 0x00, 0x0d, 0x20, 0xd6, 0xeb, 0x11, 0x00, 0x76, 0x3a, 0x8e, 0x76, 0x47, 0x2c, 0x2c, 0x1a, 0xb8, 0x38, 0x02, 0x36, 0x18, 0x2c, 0x2c, 0x2c, 0x1c, 0x7d, 0xfe, 0xc8, 0x20, 0xef, 0xc9, 0xd9, 0x21, 0x98, 0x76, 0x11, 0x99, 0x76, 0x01, 0x27, 0x00, 0x70, 0xed, 0xb0, 0xd9, 0x79, 0x32, 0x52, 0x63, 0xfd, 0x7e, 0x00, 0x32, 0xc0, 0x76, 0xc9, 0xdd, 0xe5, 0xdd, 0x21, 0x98, 0x76, 0x32, 0x62, 0x63, 0xdd, 0x36, 0x00, 0x01, 0xdd, 0xe1, 0xc9, 0xc5, 0xfd, 0xe5, 0xd5, 0xe5, 0xdd, 0xe1, 0xe5, 0x3a, 0xc0, 0x76, 0xe6, 0xf8, 0x0f, 0x0f, 0x0f, 0x4f, 0x06, 0x00, 0xeb, 0x09, 0xe5, 0xfd, 0xe1, 0x21, 0x98, 0x76, 0x3a, 0xc0, 0x76, 0xe6, 0x07, 0x4f, 0x3e, 0x07, 0x91, 0x4f, 0x16, 0x05, 0x1e, 0x7e, 0x7b, 0x32, 0x98, 0x63, 0xaf, 0xdd, 0xcb, 0x00, 0x46, 0x28, 0x02, 0x3e, 0x40, 0x08, 0x7e, 0xfe, 0x01, 0x20, 0x1b, 0x06, 0x86, 0x08, 0xb0, 0x47, 0x79, 0x07, 0x07, 0x07, 0xb0, 0x32, 0xb3, 0x63, 0xfd, 0xcb, 0x00, 0x86, 0x0d, 0x79, 0xfe, 0xff, 0x20, 0x04, 0xfd, 0x2c, 0x0e, 0x07, 0x2c, 0x7b, 0xd6, 0x08, 0x5f, 0xfe, 0x3e, 0x20, 0xc9, 0xdd, 0x23, 0x15, 0x20, 0xc2, 0xe1, 0xd1, 0x01, 0x05, 0x00, 0x09, 0xeb, 0x09, 0xeb, 0xfd, 0xe1, 0xc1, 0xc9, 0xe5, 0xdd, 0xe1, 0xd5, 0xfd, 0xe1, 0x06, 0x28, 0xc5, 0xdd, 0x4e, 0x00, 0xcd, 0x1c, 0x64, 0xdd, 0x7e, 0x04, 0xfd, 0x71, 0x04, 0x4f, 0xcd, 0x1c, 0x64, 0xfd, 0x71, 0x00, 0xdd, 0x4e, 0x01, 0xcd, 0x1c, 0x64, 0xdd, 0x7e, 0x03, 0xfd, 0x71, 0x03, 0x4f, 0xcd, 0x1c, 0x64, 0xfd, 0x71, 0x01, 0xdd, 0x4e, 0x02, 0xcd, 0x1c, 0x64, 0xfd, 0x71, 0x02, 0x01, 0x05, 0x00, 0xdd, 0x09, 0xfd, 0x09, 0xc1, 0x10, 0xc6, 0xc9, 0x06, 0x08, 0xcb, 0x19, 0x17, 0x10, 0xfb, 0x4f, 0xc9, 0xe5, 0x11, 0x00, 0x9c, 0x06, 0x05, 0xc5, 0xe5, 0x06, 0x08, 0xc5, 0xe5, 0x06, 0x28, 0xc5, 0xcb, 0x16, 0xd5, 0x06, 0x05, 0x1a, 0x1f, 0x12, 0x1c, 0x10, 0xfa, 0xd1, 0x01, 0x05, 0x00, 0x09, 0xc1, 0x10, 0xec, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0xe1, 0xc1, 0x10, 0xdf, 0xe1, 0xc1, 0x23, 0x10, 0xd6, 0xd1, 0xd5, 0x21, 0x00, 0x9c, 0x01, 0xc8, 0x00, 0xed, 0xb0, 0xe1, 0xc9, 0xdd, 0x21, 0x84, 0xac, 0x06, 0x3c, 0xdd, 0x6e, 0x00, 0xdd, 0x66, 0x01, 0xdd, 0x7e, 0x04, 0x32, 0x75, 0x64, 0xaf, 0xcb, 0x46, 0x28, 0x02, 0x3e, 0x01, 0xdd, 0x77, 0x05, 0x11, 0x06, 0x00, 0xdd, 0x19, 0x10, 0xe3, 0xc9, 0xdd, 0x21, 0x84, 0xac, 0x06, 0x14, 0xc5, 0xdd, 0x6e, 0x00, 0xdd, 0x66, 0x01, 0xdd, 0x56, 0x02, 0xdd, 0x5e, 0x03, 0xdd, 0x7e, 0x05, 0xfe, 0x01, 0x7a, 0x20, 0x01, 0x7b, 0x32, 0xa5, 0x64, 0xcb, 0x86, 0x24, 0x7c, 0xe6, 0x07, 0x20, 0x18, 0x7c, 0xd6, 0x08, 0x67, 0x7d, 0xc6, 0x20, 0x6f, 0xe6, 0xe0, 0x20, 0x0c, 0x7c, 0xc6, 0x08, 0x67, 0xe6, 0x18, 0xfe, 0x18, 0x20, 0x02, 0x26, 0x40, 0xdd, 0x75, 0x00, 0xdd, 0x74, 0x01, 0x06, 0x01, 0xcd, 0x67, 0x64, 0x3a, 0xa5, 0x64, 0xcb, 0xf7, 0x32, 0xd8, 0x64, 0xcb, 0xc6, 0xc1, 0x10, 0xaf, 0xc9, 0x0a, 0xc5, 0x4f, 0x06, 0x00, 0xdd, 0x21, 0xe0, 0x6a, 0xdd, 0x09, 0xdd, 0x7e, 0x00, 0x82, 0x57, 0xcd, 0xf7, 0x64, 0xe1, 0x7e, 0x3c, 0xe6, 0x1f, 0x77, 0xc9, 0x06, 0x05, 0xc5, 0x06, 0x08, 0xc5, 0x01, 0x05, 0x00, 0xeb, 0xed, 0xb0, 0xeb, 0x01, 0xfb, 0x00, 0x09, 0xc1, 0x10, 0xf1, 0x01, 0x20, 0xf8, 0x09, 0xc1, 0x10, 0xe7, 0xc9, 0x11, 0x9b, 0x6e, 0xd5, 0xd5, 0xd5, 0x21, 0x00, 0x40, 0xcd, 0xf7, 0x64, 0x21, 0x1b, 0x40, 0xd1, 0xcd, 0xf7, 0x64, 0x21, 0x60, 0x50, 0xd1, 0xcd, 0xf7, 0x64, 0x21, 0x7b, 0x50, 0xd1, 0xcd, 0xf7, 0x64, 0x11, 0x00, 0xa9, 0x21, 0x06, 0x40, 0xcd, 0xf7, 0x64, 0x11, 0xc8, 0xa9, 0x21, 0x0b, 0x40, 0xcd, 0xf7, 0x64, 0x11, 0x90, 0xaa, 0x21, 0x10, 0x40, 0xcd, 0xf7, 0x64, 0x11, 0x58, 0xab, 0x21, 0x15, 0x40, 0xcd, 0xf7, 0x64, 0x11, 0x06, 0x58, 0x21, 0x20, 0xac, 0x06, 0x05, 0xc5, 0x01, 0x14, 0x00, 0xed, 0xb0, 0x01, 0x0c, 0x00, 0xeb, 0x09, 0xeb, 0xc1, 0x10, 0xf1, 0xcd, 0xc2, 0x6c, 0x21, 0x00, 0xa5, 0x22, 0x36, 0x5c, 0x21, 0x00, 0x6b, 0xcd, 0x23, 0x67, 0x21, 0x00, 0x40, 0x11, 0x00, 0xc0, 0x01, 0x00, 0x1b, 0xed, 0xb0, 0xcd, 0x44, 0x6e, 0x21, 0x00, 0xc0, 0x11, 0x00, 0x40, 0x01, 0x00, 0x1b, 0xed, 0xb0, 0xcd, 0x33, 0x69, 0x3e, 0x01, 0x32, 0xbf, 0xb3, 0xdd, 0x21, 0x00, 0x9d, 0xcd, 0xca, 0x65, 0xcd, 0x4b, 0x68, 0x7e, 0x32, 0xcb, 0xb3, 0xdd, 0x22, 0xc1, 0xb3, 0x21, 0x00, 0x00, 0x22, 0x78, 0x5c, 0xaf, 0x32, 0xac, 0xde, 0x21, 0x00, 0x40, 0x11, 0x00, 0xc0, 0x01, 0x00, 0x1b, 0xed, 0xb0, 0xcd, 0x61, 0x64, 0xc9, 0xdd, 0xe5, 0xe1, 0xaf, 0x32, 0x78, 0x5c, 0x16, 0x00, 0x7e, 0xcd, 0x50, 0x67, 0xa7, 0x28, 0x22, 0xcd, 0x3a, 0x67, 0x7e, 0xa3, 0xfe, 0x42, 0x20, 0x01, 0x14, 0xfe, 0x43, 0xf5, 0x01, 0x05, 0x00, 0x09, 0xf1, 0x20, 0x06, 0x7e, 0xfe, 0xc0, 0x20, 0x01, 0x14, 0x23, 0x23, 0x23, 0x7c, 0xfe, 0xa5, 0x20, 0xd7, 0x7a, 0x32, 0xb5, 0xb3, 0x21, 0x00, 0x00, 0x22, 0xb8, 0xb3, 0x22, 0xba, 0xb3, 0x22, 0xbc, 0xb3, 0xa7, 0x20, 0x12, 0x21, 0x44, 0x6b, 0xcd, 0x23, 0x67, 0x21, 0x0b, 0x09, 0x22, 0xb6, 0xb3, 0x3e, 0x0e, 0x32, 0xbe, 0xb3, 0xc9, 0xfe, 0x0d, 0x30, 0x22, 0x32, 0xbb, 0xb3, 0x21, 0x06, 0x0e, 0x22, 0xb6, 0xb3, 0x3e, 0x01, 0x32, 0xb8, 0xb3, 0x32, 0xc0, 0xb3, 0x3e, 0x08, 0x32, 0xbe, 0xb3, 0xdd, 0xe5, 0xe1, 0x01, 0x06, 0x0a, 0x1e, 0x41, 0xcd, 0x91, 0x66, 0xc9, 0xfe, 0x19, 0x30, 0x38, 0xa7, 0x1f, 0x32, 0xbc, 0xb3, 0xce, 0x00, 0x32, 0xbb, 0xb3, 0x21, 0x06, 0x06, 0x22, 0xb6, 0xb3, 0x3e, 0x02, 0x32, 0xb8, 0xb3, 0x3d, 0x32, 0xc0, 0xb3, 0x3e, 0x08, 0x32, 0xbe, 0xb3, 0xdd, 0xe5, 0xe1, 0x01, 0x06, 0x02, 0x1e, 0x41, 0x3a, 0xbb, 0xb3, 0x57, 0xcd, 0x91, 0x66, 0x01, 0x06, 0x12, 0x3a, 0xbc, 0xb3, 0x57, 0xcd, 0x91, 0x66, 0xc9, 0x3e, 0x18, 0xcd, 0x4b, 0x66, 0x22, 0xc3, 0xb3, 0x3e, 0x01, 0x32, 0xb9, 0xb3, 0xc9, 0xed, 0x43, 0xcf, 0xb3, 0xd5, 0x7e, 0xcd, 0x50, 0x67, 0x1e, 0xff, 0xcd, 0x3a, 0x67, 0x16, 0x06, 0x7e, 0xa3, 0xfe, 0x42, 0x28, 0x14, 0xfe, 0x43, 0xf5, 0x01, 0x05, 0x00, 0x09, 0xf1, 0x20, 0x05, 0x7e, 0xfe, 0xc0, 0x28, 0x0b, 0x23, 0x23, 0x23, 0x18, 0xdb, 0x01, 0x05, 0x00, 0x09, 0x16, 0x04, 0x01, 0x0d, 0x00, 0xa7, 0xed, 0x42, 0x7a, 0x32, 0xda, 0xb3, 0x11, 0xdb, 0xb3, 0x06, 0x08, 0x7e, 0xfe, 0x20, 0x30, 0x02, 0x3e, 0x2e, 0xfe, 0x80, 0x38, 0x02, 0x3e, 0x2e, 0x12, 0x13, 0x23, 0x10, 0xee, 0x3e, 0xff, 0x12, 0xd1, 0xe5, 0x6b, 0x26, 0x3e, 0x22, 0xd5, 0xb3, 0x21, 0x20, 0x20, 0x22, 0xd7, 0xb3, 0x3e, 0x10, 0x32, 0xd9, 0xb3, 0x3e, 0x16, 0x32, 0xce, 0xb3, 0x21, 0x13, 0x01, 0x22, 0xd1, 0xb3, 0x21, 0x10, 0x05, 0x22, 0xd3, 0xb3, 0xd5, 0x21, 0xce, 0xb3, 0xcd, 0x23, 0x67, 0xd1, 0xe1, 0x01, 0x08, 0x00, 0x09, 0x3a, 0xcf, 0xb3, 0x3c, 0x32, 0xcf, 0xb3, 0x1c, 0x15, 0xc2, 0x95, 0x66, 0xc9, 0xe5, 0x2a, 0xca, 0xaf, 0xd9, 0xfd, 0x2a, 0xc8, 0xaf, 0x3e, 0x02, 0xcd, 0x01, 0x16, 0xe1, 0x7e, 0xfe, 0xff, 0xc8, 0xd7, 0x23, 0x18, 0xf8, 0xd5, 0x0e, 0x00, 0x06, 0x09, 0x11, 0x6e, 0x6b, 0x1a, 0xbe, 0x28, 0x02, 0x0e, 0xff, 0x23, 0x13, 0x10, 0xf6, 0xd1, 0x59, 0x2b, 0xc9, 0xfe, 0x01, 0xc0, 0x01, 0x10, 0x00, 0x09, 0x7e, 0x18, 0xf6, 0xfd, 0xe5, 0xdd, 0xe5, 0xe5, 0xd5, 0xc5, 0xf5, 0xd9, 0xe5, 0xd5, 0xc5, 0x2a, 0xca, 0xaf, 0xd9, 0x08, 0xf5, 0xfd, 0x2a, 0xc8, 0xaf, 0xcd, 0x56, 0xeb, 0x2a, 0x78, 0x5c, 0x23, 0x22, 0x78, 0x5c, 0x3a, 0xac, 0xde, 0xc6, 0x02, 0x32, 0xac, 0xde, 0xcd, 0xa8, 0x6b, 0xcd, 0x07, 0x6d, 0x3a, 0x78, 0x5c, 0xe6, 0x03, 0xfe, 0x03, 0x20, 0x21, 0xcd, 0x4b, 0x68, 0xed, 0x5b, 0xbe, 0xb3, 0x43, 0x72, 0x23, 0x10, 0xfc, 0xcb, 0x72, 0xcb, 0xf2, 0x28, 0x0b, 0xcb, 0xb2, 0x14, 0xcb, 0x5a, 0x28, 0x04, 0x14, 0x14, 0xcb, 0x9a, 0x7a, 0x32, 0xbf, 0xb3, 0x3a, 0x78, 0x5c, 0xfe, 0x32, 0x20, 0x58, 0x2a, 0xb6, 0xb3, 0x22, 0xcc, 0xb3, 0x3a, 0xbe, 0xb3, 0x32, 0xec, 0xb3, 0x21, 0xcc, 0xb3, 0x22, 0x4d, 0x68, 0xcd, 0x4b, 0x68, 0x2a, 0xc9, 0xb3, 0x7c, 0x07, 0x07, 0x07, 0xf6, 0xc0, 0x67, 0x22, 0xae, 0xde, 0x3a, 0xec, 0xb3, 0x47, 0xc5, 0xe5, 0x11, 0xed, 0xb3, 0xd5, 0x06, 0x08, 0x7e, 0x12, 0x24, 0x13, 0x10, 0xfa, 0xe1, 0xd1, 0xd5, 0x06, 0x08, 0x0e, 0x08, 0xe5, 0xcb, 0x16, 0x1f, 0x23, 0x0d, 0x20, 0xf9, 0x12, 0x14, 0xe1, 0x10, 0xf1, 0xe1, 0x23, 0xc1, 0x10, 0xd9, 0x21, 0xb6, 0xb3, 0x22, 0x4d, 0x68, 0xcd, 0xa5, 0x6c, 0x18, 0x1f, 0xfe, 0x3c, 0x28, 0xb0, 0xfe, 0x46, 0x28, 0xac, 0xfe, 0x50, 0x28, 0xa8, 0xfe, 0x5a, 0x20, 0x0f, 0x3e, 0xc9, 0x32, 0xdb, 0x67, 0xcd, 0xc5, 0x67, 0x3e, 0x3a, 0x32, 0xdb, 0x67, 0x18, 0xd6, 0x3a, 0x78, 0x5c, 0xe6, 0x07, 0xfe, 0x07, 0xcc, 0x67, 0x68, 0xd9, 0xf1, 0x08, 0xc1, 0xd1, 0xe1, 0xd9, 0xf1, 0xc1, 0xd1, 0xe1, 0xdd, 0xe1, 0xfd, 0xe1, 0xfb, 0xc9, 0xed, 0x5b, 0xb6, 0xb3, 0x21, 0x00, 0x00, 0x01, 0x20, 0x00, 0x7b, 0xa7, 0x28, 0x04, 0x09, 0x1d, 0x18, 0xf8, 0x4a, 0x09, 0x22, 0xc9, 0xb3, 0x01, 0x00, 0x58, 0x09, 0xc9, 0x0e, 0x41, 0x21, 0x56, 0x6b, 0x7e, 0x0f, 0x0f, 0xe6, 0x38, 0xf6, 0x87, 0x32, 0x79, 0x68, 0x3e, 0xff, 0xcb, 0x87, 0xdb, 0xfe, 0x2f, 0x47, 0x7e, 0xe6, 0x1f, 0xa0, 0xc4, 0x54, 0x6a, 0x0c, 0x23, 0x79, 0xfe, 0x59, 0x20, 0xe0, 0x3e, 0xf7, 0xdb, 0xfe, 0x1f, 0xd4, 0x6a, 0x69, 0x1f, 0xd4, 0x6a, 0x69, 0x1f, 0xd4, 0xc3, 0x69, 0x1f, 0xd4, 0x3d, 0x6a, 0x1f, 0xd4, 0x42, 0x6a, 0x3e, 0xef, 0xdb, 0xfe, 0x1f, 0xd4, 0x42, 0x6a, 0x1f, 0xd4, 0x3d, 0x6a, 0x1f, 0xd4, 0xc3, 0x69, 0x1f, 0xd4, 0x6a, 0x69, 0x1f, 0xd4, 0x6a, 0x69, 0x3e, 0x00, 0x1f, 0xdc, 0x6a, 0x69, 0x1f, 0xdc, 0x6a, 0x69, 0x1f, 0xdc, 0xc3, 0x69, 0x1f, 0xdc, 0x3d, 0x6a, 0x1f, 0xdc, 0x42, 0x6a, 0x3e, 0xfe, 0xdb, 0xfe, 0x1f, 0x38, 0x0f, 0x2a, 0xc1, 0xb3, 0x01, 0x01, 0x9d, 0xa7, 0xed, 0x42, 0x38, 0x04, 0xcd, 0x89, 0x65, 0xc9, 0x3e, 0xbf, 0xdb, 0xfe, 0x1f, 0xd4, 0x42, 0x6a, 0x3e, 0x7f, 0xdb, 0xfe, 0x1f, 0x38, 0x21, 0x2a, 0xca, 0xaf, 0xd9, 0xfd, 0x2a, 0xc8, 0xaf, 0xcd, 0x44, 0x6e, 0x21, 0x00, 0x9d, 0x11, 0x00, 0x00, 0x01, 0x05, 0x08, 0xf3, 0xed, 0x56, 0xcd, 0x13, 0x3d, 0xf3, 0xed, 0x5e, 0xcd, 0x89, 0x65, 0xc9, 0x1f, 0xd8, 0x3a, 0xb9, 0xb3, 0xa7, 0xc8, 0x2a, 0xc3, 0xb3, 0xaf, 0x32, 0xb9, 0xb3, 0x22, 0xa1, 0x65, 0xcd, 0x89, 0x65, 0x21, 0x00, 0x9d, 0x22, 0xa1, 0x65, 0xc9, 0x21, 0xc0, 0x40, 0x0e, 0x60, 0x06, 0x20, 0x36, 0x00, 0x2c, 0x10, 0xfb, 0x0d, 0x28, 0x1a, 0x7d, 0xd6, 0x20, 0x6f, 0x24, 0x7c, 0xe6, 0x07, 0x20, 0xec, 0x7c, 0xd6, 0x08, 0x67, 0x7d, 0xc6, 0x20, 0x6f, 0x20, 0xe2, 0x7c, 0xc6, 0x08, 0x67, 0x18, 0xdc, 0x21, 0xc0, 0x58, 0x11, 0xc1, 0x58, 0x01, 0x7f, 0x01, 0x36, 0x07, 0xed, 0xb0, 0xc9, 0xf5, 0x3a, 0xbc, 0xb3, 0xa7, 0x20, 0x02, 0xf1, 0xc9, 0xcd, 0x4b, 0x68, 0x3a, 0xbe, 0xb3, 0x47, 0x3a, 0xcb, 0xb3, 0x77, 0x23, 0x10, 0xfc, 0x3a, 0xbb, 0xb3, 0x47, 0x3a, 0xc0, 0xb3, 0x4f, 0x3d, 0x90, 0x30, 0x23, 0xfe, 0xff, 0x20, 0x13, 0x2a, 0xbb, 0xb3, 0x7c, 0xbd, 0x28, 0x0c, 0x3e, 0x01, 0x32, 0xc0, 0xb3, 0x3e, 0x06, 0x32, 0xb6, 0xb3, 0x18, 0x16, 0x79, 0x80, 0x32, 0xc0, 0xb3, 0x3e, 0x16, 0x32, 0xb7, 0xb3, 0x18, 0x0a, 0x79, 0x90, 0x32, 0xc0, 0xb3, 0x3e, 0x06, 0x32, 0xb7, 0xb3, 0xcd, 0x4b, 0x68, 0x7e, 0x32, 0xcb, 0xb3, 0xf1, 0xc9, 0xf5, 0x06, 0x00, 0x3a, 0xbc, 0xb3, 0xa7, 0x20, 0x09, 0x3a, 0xbb, 0xb3, 0xa7, 0x28, 0x9f, 0x3d, 0x28, 0x9c, 0xc5, 0xcd, 0x4b, 0x68, 0x3a, 0xbe, 0xb3, 0x47, 0x3a, 0xcb, 0xb3, 0x77, 0x23, 0x10, 0xfc, 0xc1, 0x3a, 0xc0, 0xb3, 0x4f, 0xed, 0x5b, 0xbb, 0xb3, 0x3a, 0xb6, 0xb3, 0x6f, 0x3a, 0xb7, 0xb3, 0xfe, 0x16, 0x28, 0x21, 0x78, 0xa7, 0x20, 0x0e, 0x79, 0xbb, 0x3e, 0x06, 0x26, 0x01, 0x28, 0x2f, 0x61, 0x24, 0x7d, 0x3c, 0x18, 0x29, 0x79, 0xfe, 0x01, 0x20, 0x04, 0x63, 0x7b, 0x18, 0x1e, 0x61, 0x25, 0x7d, 0x3d, 0x18, 0x1a, 0x78, 0xa7, 0x20, 0x0b, 0x7b, 0x82, 0xb9, 0x20, 0xe2, 0x63, 0x24, 0x3e, 0x06, 0x18, 0x0b, 0x7b, 0x3c, 0xb9, 0x20, 0xe6, 0x7b, 0x82, 0x67, 0x7a, 0xc6, 0x05, 0x32, 0xb6, 0xb3, 0x7c, 0x32, 0xc0, 0xb3, 0xc3, 0xba, 0x69, 0x06, 0x01, 0xf5, 0x18, 0x84, 0xf5, 0x3a, 0xbb, 0xb3, 0x47, 0x3a, 0xbc, 0xb3, 0xb0, 0xca, 0x71, 0x69, 0x3a, 0xc0, 0xb3, 0xc6, 0x40, 0x4f, 0x3a, 0xb5, 0xb3, 0xc6, 0x40, 0xb9, 0xd8, 0x06, 0x40, 0xd9, 0x2a, 0xc1, 0xb3, 0x7e, 0xcd, 0x50, 0x67, 0x1e, 0xff, 0xcd, 0x3a, 0x67, 0x16, 0xec, 0x7e, 0xa3, 0xfe, 0x42, 0x28, 0x14, 0xfe, 0x43, 0xf5, 0x01, 0x05, 0x00, 0x09, 0xf1, 0x20, 0x05, 0x7e, 0xfe, 0xc0, 0x28, 0x0b, 0x23, 0x23, 0x23, 0x18, 0xdb, 0x01, 0x05, 0x00, 0x09, 0x16, 0xf7, 0x01, 0x0d, 0x00, 0xa7, 0xed, 0x42, 0xd9, 0x04, 0x78, 0xb9, 0xd9, 0x7e, 0x36, 0x01, 0x20, 0xc5, 0x77, 0xd5, 0xe5, 0x21, 0x4c, 0x5d, 0x72, 0x23, 0x23, 0xeb, 0xe1, 0x01, 0x08, 0x00, 0xed, 0xb0, 0x13, 0x0e, 0x20, 0xe1, 0x7c, 0xfe, 0xf7, 0x28, 0x02, 0x0e, 0xaf, 0x79, 0x12, 0x21, 0x00, 0x00, 0x22, 0x78, 0x5c, 0x3a, 0xce, 0xaf, 0xed, 0x47, 0x2a, 0xca, 0xaf, 0xd9, 0xfd, 0x2a, 0xc8, 0xaf, 0xed, 0x7b, 0xcc, 0xaf, 0x21, 0x00, 0x3c, 0x22, 0x36, 0x5c, 0xcd, 0x4b, 0x6e, 0xcd, 0x75, 0x6e, 0xed, 0x56, 0xfb, 0xc9, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x10, 0x0f, 0x0e, 0x0d, 0x0c, 0x0b, 0x0a, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x08, 0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01, 0x16, 0x13, 0x07, 0x13, 0x01, 0x10, 0x05, 0x53, 0x50, 0x41, 0x43, 0x45, 0x20, 0x20, 0x54, 0x4f, 0x20, 0x4e, 0x45, 0x57, 0x20, 0x44, 0x49, 0x53, 0x4b, 0x16, 0x14, 0x07, 0x22, 0x53, 0x53, 0x22, 0x20, 0x54, 0x4f, 0x20, 0x4e, 0x45, 0x58, 0x54, 0x20, 0x50, 0x41, 0x47, 0x45, 0x53, 0x16, 0x15, 0x07, 0x22, 0x43, 0x53, 0x22, 0x20, 0x54, 0x4f, 0x20, 0x46, 0x49, 0x52, 0x53, 0x54, 0x20, 0x50, 0x41, 0x47, 0x45, 0xff, 0x16, 0x0b, 0x09, 0x4e, 0x4f, 0x20, 0x45, 0x58, 0x45, 0x20, 0x46, 0x49, 0x4c, 0x45, 0x53, 0x20, 0x21, 0xff, 0x21, 0xf0, 0x08, 0x24, 0x44, 0x28, 0x30, 0xd0, 0xa4, 0xc8, 0xc4, 0xc2, 0xe4, 0xe8, 0xa2, 0xa1, 0x41, 0x48, 0x22, 0x50, 0xa8, 0x10, 0x42, 0x04, 0x62, 0x6f, 0x6f, 0x74, 0x20, 0x20, 0x20, 0x20, 0x42, 0x08, 0x10, 0x13, 0x17, 0x1f, 0x05, 0x0c, 0x15, 0x1b, 0x22, 0x01, 0x03, 0x0a, 0x1d, 0x24, 0x27, 0x07, 0x0e, 0x19, 0x20, 0x02, 0x0b, 0x12, 0x16, 0x1c, 0x26, 0x00, 0x0f, 0x1e, 0x23, 0x09, 0x04, 0x11, 0x18, 0x25, 0x14, 0x06, 0x0d, 0x1a, 0x21, 0x13, 0x12, 0x0f, 0x0c, 0x0a, 0x07, 0x05, 0x02, 0x00, 0x3a, 0xac, 0xde, 0xa7, 0x20, 0x20, 0x2a, 0xa8, 0xde, 0x23, 0x7c, 0xe6, 0x07, 0x67, 0x22, 0xa8, 0xde, 0x06, 0x08, 0x4e, 0x21, 0xec, 0xad, 0xed, 0x5f, 0xae, 0xa9, 0x81, 0x4f, 0x3a, 0xb0, 0xb3, 0xa9, 0x77, 0x23, 0x10, 0xf2, 0xc9, 0x3a, 0xac, 0xde, 0xe6, 0x3f, 0xfe, 0x3e, 0x20, 0x21, 0x3a, 0xb0, 0xde, 0x3c, 0xe6, 0x07, 0x32, 0xb0, 0xde, 0x28, 0x08, 0x3a, 0xac, 0xde, 0xd6, 0x02, 0x32, 0xac, 0xde, 0x3e, 0xc9, 0x32, 0x1c, 0x6c, 0xcd, 0x00, 0x6c, 0x3e, 0x3a, 0x32, 0x1c, 0x6c, 0xc9, 0x3a, 0xac, 0xde, 0xe6, 0x07, 0xfe, 0x02, 0xc0, 0x3a, 0xac, 0xde, 0x07, 0x07, 0x07, 0xe6, 0x06, 0x4f, 0x06, 0x00, 0x21, 0xec, 0xad, 0x09, 0xcd, 0x59, 0x6c, 0xf5, 0xd4, 0xae, 0x6b, 0xf1, 0x30, 0xe7, 0xcd, 0x74, 0x6c, 0x3a, 0xac, 0xde, 0xe6, 0x20, 0x0e, 0x60, 0x20, 0x02, 0x0e, 0x00, 0x3a, 0xac, 0xde, 0x07, 0x07, 0xa9, 0xe6, 0x60, 0x4f, 0x06, 0x00, 0x21, 0x63, 0x6f, 0x09, 0xeb, 0x06, 0x10, 0x2a, 0xaa, 0xde, 0x4e, 0x1a, 0xb1, 0x77, 0x2c, 0x13, 0x4e, 0x1a, 0xb1, 0x77, 0x13, 0x2d, 0x24, 0x7c, 0xe6, 0x07, 0x20, 0x08, 0x7c, 0xd6, 0x08, 0x67, 0x7d, 0xc6, 0x20, 0x6f, 0x10, 0xe4, 0xc9, 0x06, 0x1a, 0x23, 0x7e, 0xe6, 0x18, 0x28, 0x06, 0xfe, 0x10, 0x28, 0x02, 0x06, 0x1f, 0x2b, 0x7e, 0xfe, 0xe0, 0xd0, 0xe6, 0x1f, 0xb8, 0xd0, 0xee, 0x1f, 0xb8, 0xc9, 0x23, 0x7e, 0xe6, 0x18, 0xfe, 0x18, 0x20, 0x02, 0x3e, 0x08, 0x2b, 0x6e, 0xf6, 0x40, 0x67, 0x22, 0xaa, 0xde, 0x06, 0x10, 0x7c, 0xf6, 0x80, 0x57, 0x5d, 0x1a, 0x77, 0x2c, 0x1c, 0x1a, 0x77, 0x2d, 0x24, 0x7c, 0xe6, 0x07, 0x20, 0x08, 0x7c, 0xd6, 0x08, 0x67, 0x7d, 0xc6, 0x20, 0x6f, 0x10, 0xe4, 0xc9, 0x2a, 0xae, 0xde, 0x7c, 0xe6, 0x7f, 0x57, 0x5d, 0x06, 0x08, 0xc5, 0x3a, 0xec, 0xb3, 0x4f, 0x06, 0x00, 0xe5, 0xd5, 0xed, 0xb0, 0xd1, 0xe1, 0x24, 0x14, 0xc1, 0x10, 0xee, 0xc9, 0x21, 0x00, 0x58, 0xcd, 0xdb, 0x6c, 0x21, 0x7b, 0x5a, 0xcd, 0xdb, 0x6c, 0x11, 0x1b, 0x58, 0xcd, 0xf2, 0x6c, 0x11, 0x60, 0x5a, 0xcd, 0xf2, 0x6c, 0xc9, 0x06, 0x05, 0x11, 0xf4, 0xad, 0x0e, 0x05, 0x1a, 0x77, 0x23, 0x0d, 0x20, 0xfb, 0x13, 0xc5, 0x01, 0x1b, 0x00, 0x09, 0xc1, 0x10, 0xef, 0xc9, 0x06, 0x05, 0xc5, 0x01, 0x05, 0x00, 0x21, 0xf4, 0xad, 0xed, 0xb0, 0xeb, 0x01, 0x1b, 0x00, 0x09, 0xeb, 0xc1, 0x10, 0xee, 0xc9, 0x3a, 0x78, 0x5c, 0xfe, 0x40, 0xd0, 0x21, 0x06, 0x58, 0x22, 0x41, 0x6d, 0x21, 0x19, 0x58, 0x22, 0x44, 0x6d, 0x21, 0x80, 0x58, 0x22, 0x57, 0x6d, 0x3a, 0x79, 0x5c, 0xe6, 0x01, 0x28, 0x12, 0x21, 0x66, 0x5a, 0x22, 0x41, 0x6d, 0x21, 0x79, 0x5a, 0x22, 0x44, 0x6d, 0x21, 0xe0, 0x5a, 0x22, 0x57, 0x6d, 0x3a, 0x78, 0x5c, 0xa7, 0x20, 0x09, 0x3e, 0x02, 0x32, 0x06, 0x58, 0x32, 0x19, 0x58, 0xc9, 0xe6, 0x01, 0xc0, 0x3a, 0x78, 0x5c, 0x0f, 0xe6, 0x1f, 0xfe, 0x1b, 0xd0, 0x4f, 0x06, 0x05, 0x21, 0x80, 0x58, 0x0d, 0xcd, 0x6d, 0x6d, 0x0c, 0xcd, 0x8d, 0x6d, 0x0c, 0xc5, 0x01, 0x20, 0x00, 0xa7, 0xed, 0x42, 0xc1, 0x10, 0xed, 0xc9, 0xc5, 0xe5, 0x7d, 0xb1, 0x6f, 0x5d, 0x7c, 0xf6, 0x80, 0x57, 0xe5, 0xd5, 0xeb, 0x01, 0x03, 0x00, 0xed, 0xb0, 0xe1, 0xd1, 0x7d, 0xee, 0x1f, 0x6f, 0x5d, 0x0e, 0x03, 0xed, 0xb8, 0xe1, 0xc1, 0xc9, 0xc5, 0xe5, 0x7d, 0xb1, 0x6f, 0xe5, 0xcd, 0xb1, 0x6d, 0x23, 0xcd, 0xbd, 0x6d, 0x23, 0xcd, 0xb1, 0x6d, 0xe1, 0x7d, 0xee, 0x1f, 0x6f, 0xcd, 0xb1, 0x6d, 0x2b, 0xcd, 0xbd, 0x6d, 0x2b, 0xcd, 0xb1, 0x6d, 0xe1, 0xc1, 0xc9, 0x7d, 0xe6, 0x1f, 0xfe, 0x06, 0xd8, 0xfe, 0x1a, 0xd0, 0x36, 0x02, 0xc9, 0x7d, 0xe6, 0x1f, 0xfe, 0x06, 0xd8, 0xfe, 0x1a, 0xd0, 0x36, 0x42, 0xc9, 0x21, 0x00, 0xa9, 0xcd, 0x38, 0x6e, 0x21, 0xc8, 0xa9, 0xcd, 0x38, 0x6e, 0x21, 0x90, 0xaa, 0xcd, 0x38, 0x6e, 0x21, 0x58, 0xab, 0xcd, 0x38, 0x6e, 0xf3, 0x11, 0x00, 0xa9, 0x21, 0x66, 0xd0, 0xcd, 0xf7, 0x64, 0x11, 0xc8, 0xa9, 0x21, 0x6b, 0xd0, 0xcd, 0xf7, 0x64, 0x11, 0x90, 0xaa, 0x21, 0x70, 0xd0, 0xcd, 0xf7, 0x64, 0x11, 0x58, 0xab, 0x21, 0x75, 0xd0, 0xcd, 0xf7, 0x64, 0x06, 0x05, 0x21, 0x06, 0xd8, 0x11, 0xe6, 0xda, 0xc5, 0x01, 0x14, 0x00, 0xed, 0xb0, 0x0e, 0x0c, 0x09, 0x0e, 0x34, 0xa7, 0xeb, 0xed, 0x42, 0xeb, 0xc1, 0x10, 0xed, 0x21, 0x00, 0xd0, 0x11, 0x00, 0x50, 0x01, 0x00, 0x08, 0xed, 0xb0, 0x21, 0x60, 0xda, 0x11, 0x60, 0x5a, 0x0e, 0xa0, 0xed, 0xb0, 0xfb, 0xc9, 0xcd, 0x25, 0x64, 0xcd, 0x25, 0x64, 0x54, 0x5d, 0xcd, 0xd9, 0x63, 0xc9, 0x21, 0x30, 0x75, 0xcd, 0x52, 0x6e, 0xc9, 0x21, 0x67, 0x6e, 0xcd, 0x52, 0x6e, 0xc9, 0xaf, 0x01, 0xfd, 0xff, 0xed, 0x79, 0xf5, 0x7e, 0x01, 0xfd, 0xbf, 0xed, 0x79, 0x23, 0xf1, 0x3c, 0xfe, 0x0e, 0xc8, 0x18, 0xec, 0x30, 0x00, 0x01, 0x00, 0x50, 0x00, 0x00, 0x38, 0x10, 0x10, 0x10, 0xc4, 0x50, 0x01, 0x16, 0x08, 0x0e, 0x10, 0x21, 0x00, 0x40, 0x41, 0xaf, 0xcb, 0x1e, 0x23, 0xaf, 0xcb, 0x16, 0x23, 0x10, 0xf6, 0x41, 0xaf, 0xcb, 0x16, 0x23, 0xaf, 0xcb, 0x1e, 0x23, 0x10, 0xf6, 0x7c, 0xfe, 0x58, 0x20, 0xe5, 0x15, 0x20, 0xdd, 0xc9, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, 0x00, 0x72, 0x00, 0x00, 0x00, 0x00, 0xb1, 0x00, 0x00, 0x00, 0x01, 0xe0, 0x80, 0x00, 0x00, 0x03, 0xd0, 0x40, 0x00, 0x00, 0x07, 0xa8, 0x20, 0x00, 0x00, 0x0b, 0x54, 0x10, 0x00, 0x00, 0x1e, 0xaa, 0x08, 0x00, 0x00, 0x2d, 0x55, 0x04, 0x00, 0x00, 0x7a, 0xaa, 0x82, 0x00, 0x00, 0xb5, 0x55, 0x41, 0x00, 0x01, 0x6a, 0xaa, 0xa0, 0x80, 0x02, 0xd5, 0x45, 0x50, 0x40, 0x05, 0x2a, 0x82, 0xa8, 0x20, 0x09, 0x55, 0x01, 0x54, 0x10, 0x12, 0xaa, 0x00, 0xaa, 0x08, 0x25, 0x54, 0x00, 0x55, 0x04, 0x22, 0xa8, 0x00, 0x2a, 0x84, 0x25, 0x50, 0x00, 0x15, 0x44, 0x2a, 0xa4, 0x00, 0x3a, 0xa4, 0x35, 0x42, 0x00, 0x7d, 0x54, 0x2a, 0xa1, 0x00, 0xba, 0xa8, 0x15, 0x51, 0x01, 0xf5, 0x50, 0x0a, 0xa9, 0x03, 0xea, 0xa0, 0x05, 0x55, 0x05, 0xd5, 0x40, 0x02, 0xab, 0x0f, 0xaa, 0x80, 0x01, 0x55, 0x17, 0x55, 0x00, 0x00, 0xaa, 0x2e, 0xaa, 0x00, 0x00, 0x54, 0x55, 0x54, 0x00, 0x00, 0x28, 0x9a, 0xa8, 0x00, 0x00, 0x11, 0x35, 0x50, 0x00, 0x00, 0x01, 0x2a, 0xa0, 0x00, 0x00, 0x01, 0x55, 0x40, 0x00, 0x00, 0x01, 0xaa, 0x80, 0x00, 0x00, 0x01, 0x55, 0x00, 0x00, 0x00, 0x00, 0xaa, 0x00, 0x00, 0x00, 0x00, 0x54, 0x00, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x01, 0xc0, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 0x05, 0xd0, 0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 0x00, 0x90, 0x02, 0x80, 0x01, 0xc0, 0x2f, 0xf4, 0x01, 0xc0, 0x00, 0xa0, 0x04, 0x80, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 0x10, 0x08, 0x00, 0x80, 0x04, 0x80, 0x02, 0xa0, 0x01, 0xc0, 0x5f, 0xfd, 0x01, 0xc0, 0x02, 0x80, 0x04, 0x90, 0x00, 0x88, 0x10, 0x80, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x38, 0x10, 0x10, 0x00, 0x10, 0x00, 0x00, 0x36, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x24, 0x7e, 0x24, 0x24, 0x7e, 0x24, 0x00, 0x00, 0x08, 0x3e, 0x68, 0x3e, 0x0a, 0x7e, 0x08, 0x00, 0x66, 0x4c, 0x18, 0x30, 0x66, 0x4e, 0x00, 0x18, 0x24, 0x2c, 0x78, 0xda, 0xcc, 0x7e, 0x00, 0x18, 0x18, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x18, 0x18, 0x18, 0x18, 0x0c, 0x00, 0x00, 0x30, 0x18, 0x18, 0x18, 0x18, 0x30, 0x00, 0x00, 0x00, 0x14, 0x08, 0x7e, 0x18, 0x2c, 0x00, 0x00, 0x00, 0x08, 0x08, 0x7e, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x30, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x78, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x06, 0x0c, 0x18, 0x30, 0x60, 0x00, 0x38, 0x6c, 0xce, 0xd6, 0xe6, 0x6c, 0x38, 0x00, 0x18, 0x38, 0x78, 0x18, 0x18, 0x3e, 0x7c, 0x00, 0x78, 0xcc, 0x1c, 0x38, 0x70, 0xe6, 0xfe, 0x00, 0x7e, 0xcc, 0x18, 0x3c, 0x0e, 0xce, 0x7c, 0x00, 0x24, 0x6c, 0xcc, 0xcc, 0xfc, 0x0c, 0x0c, 0x00, 0xfe, 0xc2, 0xf8, 0xcc, 0x0e, 0xce, 0x7c, 0x00, 0x7c, 0xc6, 0xc0, 0xfc, 0xc6, 0xc6, 0x7c, 0x00, 0x7e, 0x66, 0x0e, 0x1c, 0x38, 0x30, 0x30, 0x00, 0x7c, 0xc6, 0x7c, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x7c, 0xc6, 0xc6, 0x7e, 0x06, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x18, 0x18, 0x30, 0x00, 0x00, 0x0c, 0x18, 0x30, 0x18, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x30, 0x18, 0x0c, 0x18, 0x30, 0x00, 0x7c, 0xc6, 0xc6, 0x1c, 0x30, 0x00, 0x30, 0x00, 0x00, 0x3c, 0x4a, 0x56, 0xfe, 0xc0, 0x7c, 0x00, 0x3c, 0x66, 0xc6, 0xfe, 0xc6, 0xe6, 0x66, 0x00, 0xf8, 0xcc, 0xcc, 0xfc, 0xc6, 0xc6, 0xfc, 0x00, 0x38, 0x6c, 0xc6, 0xc0, 0xc0, 0xe6, 0x7c, 0x00, 0xf8, 0xcc, 0xc6, 0xc6, 0xc6, 0xcc, 0xf8, 0x00, 0xfe, 0xe6, 0x60, 0x7c, 0x60, 0xe6, 0xfe, 0x00, 0xfe, 0xe6, 0x60, 0x7c, 0x60, 0xe0, 0xc0, 0x00, 0x3c, 0x66, 0xc0, 0xde, 0xc6, 0xee, 0x7c, 0x00, 0xc4, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0x46, 0x00, 0x7e, 0x98, 0x30, 0x30, 0x30, 0x1a, 0xfc, 0x00, 0x3e, 0x0c, 0x0c, 0xe6, 0x66, 0xc6, 0x7c, 0x00, 0xe6, 0x6c, 0x78, 0x70, 0x78, 0x6c, 0xc6, 0x00, 0xc0, 0xe0, 0x60, 0x60, 0x60, 0xe6, 0xfe, 0x00, 0x46, 0xee, 0xfe, 0xd6, 0xd6, 0xc6, 0x46, 0x00, 0xc4, 0xe6, 0xf6, 0xde, 0xce, 0xce, 0x46, 0x00, 0x38, 0x6c, 0xc6, 0xc6, 0xc6, 0xee, 0x7c, 0x00, 0xfc, 0xe6, 0xc6, 0xce, 0xfc, 0xc0, 0xc0, 0x00, 0x38, 0x6c, 0xc6, 0xd6, 0xce, 0xec, 0x7a, 0x00, 0xfc, 0xc6, 0xc6, 0xfc, 0xd8, 0xcc, 0xc6, 0x00, 0x3e, 0x66, 0x70, 0x1c, 0xc6, 0xc6, 0x7c, 0x00, 0xfe, 0xba, 0x18, 0x18, 0x18, 0x38, 0x30, 0x00, 0xe6, 0x66, 0xc6, 0xc6, 0xc6, 0xe6, 0x7c, 0x00, 0xce, 0xcc, 0xc6, 0xc6, 0x66, 0x7c, 0x38, 0x00, 0xce, 0xc6, 0xd6, 0xd6, 0xfe, 0xfe, 0x6c, 0x00, 0xc6, 0xee, 0x6c, 0x38, 0x6c, 0xee, 0xc6, 0x00, 0xc6, 0xc6, 0x6e, 0x3c, 0x18, 0x18, 0x18, 0x00, 0x76, 0xec, 0x98, 0x30, 0x62, 0xde, 0xbc, 0x00, 0x00, 0x1c, 0x10, 0x10, 0x30, 0x30, 0x3c, 0x00, 0x00, 0x40, 0x60, 0x30, 0x18, 0x0c, 0x06, 0x00, 0x00, 0x1c, 0x04, 0x04, 0x0c, 0x0c, 0x3c, 0x00, 0x00, 0x08, 0x1c, 0x2a, 0x08, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x1c, 0x22, 0x78, 0x60, 0x60, 0xfc, 0x00, 0x00, 0x00, 0x1c, 0x02, 0x3e, 0x66, 0x3e, 0x00, 0x00, 0x20, 0x20, 0x3c, 0x66, 0x66, 0x7c, 0x00, 0x00, 0x00, 0x1c, 0x20, 0x60, 0x60, 0x3c, 0x00, 0x00, 0x02, 0x02, 0x1e, 0x66, 0x66, 0x3e, 0x00, 0x00, 0x00, 0x1c, 0x22, 0x7c, 0x60, 0x3e, 0x00, 0x00, 0x0c, 0x10, 0x18, 0x30, 0x30, 0x30, 0x00, 0x00, 0x00, 0x1e, 0x22, 0x66, 0x3e, 0x06, 0x3c, 0x00, 0x20, 0x20, 0x3c, 0x66, 0x66, 0x66, 0x00, 0x00, 0x08, 0x00, 0x08, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x04, 0x00, 0x04, 0x0c, 0x0c, 0x6c, 0x38, 0x00, 0x20, 0x28, 0x30, 0x70, 0x78, 0x6c, 0x00, 0x00, 0x10, 0x10, 0x10, 0x30, 0x30, 0x1c, 0x00, 0x00, 0x00, 0x34, 0x2a, 0x6a, 0x6a, 0x6a, 0x00, 0x00, 0x00, 0x3c, 0x22, 0x66, 0x66, 0x66, 0x00, 0x00, 0x00, 0x1c, 0x22, 0x66, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x3c, 0x22, 0x66, 0x7c, 0x60, 0x60, 0x00, 0x00, 0x3c, 0x44, 0xcc, 0x7c, 0x0c, 0x0e, 0x00, 0x00, 0x1c, 0x20, 0x60, 0x60, 0x60, 0x00, 0x00, 0x00, 0x1c, 0x20, 0x3c, 0x06, 0x7c, 0x00, 0x00, 0x10, 0x38, 0x10, 0x30, 0x30, 0x1c, 0x00, 0x00, 0x00, 0x22, 0x22, 0x66, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x44, 0x44, 0x6c, 0x38, 0x10, 0x00, 0x00, 0x00, 0x22, 0x2a, 0x6a, 0x7e, 0x3c, 0x00, 0x00, 0x00, 0x22, 0x14, 0x18, 0x3c, 0x66, 0x00, 0x00, 0x00, 0x22, 0x22, 0x66, 0x3e, 0x06, 0x3c, 0x00, 0x00, 0x3e, 0x04, 0x18, 0x30, 0x7e, 0x00, 0x00, 0x0e, 0x08, 0x30, 0x10, 0x18, 0x1e, 0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x38, 0x08, 0x04, 0x08, 0x18, 0x78, 0x00, 0x00, 0x12, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x42, 0x99, 0xa1, 0xa1, 0x99, 0x42, 0x3c, 0x09, 0x20, 0x00, 0x00, 0x00, 0x05, 0x4c, 0x00, 0x00, 0x00, 0x02, 0x91, 0xc0, 0x00, 0x07, 0xbe, 0xe4, 0x1e, 0x00, 0x70, 0x02, 0x7e, 0xa0, 0xff, 0x02, 0x01, 0x21, 0xf5, 0x00, 0x57, 0x09, 0x60, 0x1f, 0x95, 0xf8, 0x01, 0x20, 0x00, 0xff, 0xe0, 0x01, 0x11, 0xfc, 0x2d, 0xff, 0x01, 0x13, 0x9f, 0xff, 0xe1, 0x00, 0x17, 0xff, 0xff, 0x99, 0x01, 0x16, 0x04, 0xbf, 0xfe, 0x00, 0x2c, 0x01, 0xfd, 0xdf, 0x01, 0x2c, 0xff, 0x07, 0x57, 0x00, 0x3f, 0x00, 0x0e, 0xbb, 0x00, 0x78, 0x00, 0x0a, 0x96, 0x00, 0x00, 0x00, 0x15, 0x02, 0x00, 0x10, 0x00, 0x20, 0x0c, 0x00, 0x00, 0x00, 0x51, 0x04, 0x00, 0x10, 0x00, 0x80, 0x09, 0x00, 0x10, 0x83, 0x00, 0x12, 0x01, 0x10, 0x0a, 0x00, 0xa4, 0x00, 0x12, 0x3c, 0x21, 0x48, 0x00, 0x54, 0xd2, 0x12, 0xb0, 0x00, 0x3b, 0x29, 0x41, 0x50, 0x57, 0xec, 0xd1, 0x22, 0xa0, 0x00, 0x5b, 0xe4, 0x0c, 0x40, 0x00, 0xbf, 0x5b, 0x58, 0x80, 0x00, 0x77, 0xff, 0xf1, 0x03, 0x02, 0xdf, 0xb7, 0x56, 0xfc, 0x01, 0xbf, 0xff, 0xe8, 0x00, 0x01, 0x3f, 0x7f, 0xc7, 0x29, 0x02, 0x63, 0xc7, 0xf1, 0xff, 0x02, 0xdf, 0x8b, 0xf8, 0x1b, 0x04, 0x07, 0xfe, 0xdf, 0xff, 0x04, 0x01, 0xff, 0xff, 0xff, 0x04, 0xf8, 0x7f, 0xef, 0xff, 0x0b, 0x07, 0x8b, 0xff, 0x02, 0x0c, 0x00, 0x7f, 0x74, 0x1f, 0x08, 0x00, 0x00, 0xff, 0xf0, 0x07, 0x00, 0x00, 0x0f, 0xc0, 0x71, 0x00, 0x00, 0x10, 0x38, 0x02, 0x80, 0x00, 0x2f, 0x8c, 0x5e, 0x80, 0x00, 0x60, 0x72, 0xe4, 0x80, 0x00, 0x40, 0x99, 0x85, 0x00, 0x00, 0x43, 0x79, 0x09, 0x00, 0x00, 0x45, 0xfc, 0x0a, 0x00, 0x00, 0x4b, 0xb4, 0x12, 0x00, 0x00, 0x2f, 0x94, 0x92, 0x00, 0x00, 0x2f, 0x12, 0xe4, 0x00, 0x01, 0x17, 0x9a, 0xd8, 0x00, 0x00, 0x17, 0x89, 0xa8, 0x00, 0x00, 0x0f, 0xdd, 0x90, 0x00, 0x01, 0x05, 0xfc, 0x60, 0x00, 0x00, 0x03, 0xfc, 0xa0, 0x00, 0x21, 0x01, 0x7e, 0xc0, 0x00, 0x09, 0x00, 0xef, 0x40, 0x00, 0x05, 0x40, 0x3f, 0x80, 0x00, 0x03, 0x80, 0x0b, 0x00, 0x05, 0xbe, 0xea, 0x45, 0x00, 0x00, 0x01, 0x80, 0x02, 0x00, 0x00, 0x03, 0x40, 0x02, 0x00, 0x00, 0x0d, 0x00, 0x01, 0x00, 0x00, 0x31, 0x10, 0x01, 0x00, 0x00, 0xe1, 0x00, 0x00, 0x00, 0x0f, 0x79, 0x00, 0x00, 0x00, 0x77, 0xb7, 0x00, 0x00, 0x0f, 0x98, 0xb3, 0x00, 0x09, 0xf0, 0x26, 0x6a, 0x00, 0x01, 0x02, 0xbc, 0x4a, 0x00, 0x09, 0xa7, 0xfd, 0x84, 0x00, 0x82, 0xf9, 0xf7, 0x18, 0x00, 0x0b, 0xe1, 0xbc, 0x70, 0x00, 0x2a, 0x8f, 0xf0, 0xc0, 0x00, 0x1a, 0xff, 0xe3, 0x00, 0x05, 0xf4, 0xff, 0x8c, 0x00, 0x00, 0x1c, 0xec, 0xf0, 0x00, 0x00, 0x2c, 0xff, 0x00, 0x00, 0x00, 0x4c, 0xe0, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x01, 0x00, 0x0f, 0x40, 0x0e, 0x00, 0x00, 0x30, 0x00, 0x11, 0xc1, 0x10, 0x4f, 0x48, 0x2c, 0x31, 0x00, 0x70, 0x50, 0x43, 0x89, 0x40, 0x80, 0x2d, 0x40, 0x75, 0x80, 0x83, 0xd0, 0x81, 0x92, 0xea, 0x87, 0xc0, 0x87, 0x8b, 0x80, 0x47, 0x80, 0x9f, 0xcb, 0x00, 0x4d, 0x41, 0x3d, 0xcb, 0x20, 0x2e, 0x41, 0x7d, 0x93, 0x00, 0x3e, 0x42, 0xf7, 0x95, 0x00, 0x16, 0x27, 0xe7, 0xa4, 0x00, 0x0e, 0x95, 0xcf, 0x29, 0x00, 0x05, 0x4f, 0xdf, 0x48, 0x00, 0x02, 0x6f, 0xfe, 0x91, 0x00, 0x01, 0xfb, 0xff, 0xa0, 0x00, 0x00, 0xdf, 0xfb, 0x40, 0x00, 0x00, 0xff, 0xb6, 0x80, 0x00, 0x00, 0xbf, 0xa4, 0x80, 0x00, 0x40, 0xdb, 0x45, 0x00, 0x00, 0x00, 0x58, 0x05, 0x00, 0x00, 0x40, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x04, 0x0a, 0x00, 0x04, 0x42, 0x80, 0x8a, 0x00, 0x00, 0x47, 0x80, 0x01, 0x00, 0x01, 0x4f, 0x80, 0x25, 0x00, 0x00, 0xf7, 0x52, 0x45, 0x01, 0x5f, 0xaf, 0x41, 0xa8, 0x80, 0x00, 0x3f, 0x56, 0xf2, 0x80, 0x01, 0x5f, 0xfb, 0xb6, 0x80, 0x02, 0xbb, 0xff, 0xfa, 0x40, 0x00, 0xbf, 0xe6, 0xfd, 0x40, 0x09, 0x6f, 0xcf, 0xf9, 0x40, 0x01, 0x5d, 0xe7, 0xf8, 0x80, 0x01, 0x1f, 0x7f, 0xf1, 0x00, 0x02, 0x17, 0x12, 0x8e, 0x00, 0x02, 0x0f, 0x00, 0x1c, 0x00, 0x02, 0x04, 0x03, 0xe0, 0x00, 0x03, 0x01, 0xfc, 0x00, 0x00, 0x01, 0xfe, 0xf0, 0x00, 0x00, 0x20, 0x00, 0x10, 0x00, 0x3e, 0xa8, 0x00, 0xec, 0x00, 0x41, 0xf0, 0x00, 0x72, 0x00, 0xbc, 0xdf, 0x60, 0xca, 0x01, 0x03, 0x30, 0x00, 0xc9, 0x02, 0x60, 0xa8, 0x00, 0xe5, 0x04, 0xf0, 0xa0, 0x00, 0xf4, 0x85, 0xcc, 0xa2, 0x00, 0xfa, 0x4f, 0xce, 0x20, 0x00, 0x7f, 0x5b, 0x8d, 0x40, 0x00, 0x7b, 0x3f, 0x9e, 0x40, 0x00, 0x7f, 0xbf, 0xba, 0xa0, 0x00, 0xdb, 0xfd, 0x74, 0xa0, 0x00, 0xbf, 0xb7, 0xf5, 0x00, 0x00, 0x4d, 0xf7, 0x49, 0x20, 0x00, 0x19, 0x11, 0x0a, 0x00, 0x00, 0x00, 0x54, 0xb2, 0x00, 0x00, 0x42, 0x01, 0x2c, 0x00, 0x00, 0x20, 0x00, 0x12, 0x00, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x40, 0x10, 0xc5, 0x00, 0x00, 0xa1, 0x04, 0x24, 0x80, 0x00, 0x02, 0x00, 0x2a, 0x40, 0x00, 0x74, 0x20, 0x6b, 0x40, 0x00, 0x69, 0x59, 0x5f, 0x21, 0x00, 0xad, 0x5b, 0xde, 0xa0, 0x00, 0xfd, 0xaf, 0xf7, 0x91, 0x00, 0x6f, 0x27, 0x73, 0x50, 0x00, 0xff, 0x47, 0xfb, 0xc9, 0x00, 0xde, 0x85, 0xb9, 0xa9, 0x10, 0xbd, 0x03, 0xbc, 0xa5, 0x00, 0x3d, 0x02, 0xfc, 0xd5, 0x40, 0x3a, 0x02, 0xdc, 0xd5, 0x80, 0xba, 0x01, 0x5c, 0xd2, 0xf5, 0xf4, 0x01, 0x3c, 0xcb, 0x80, 0x68, 0x00, 0x8b, 0xcd, 0x00, 0xb0, 0x00, 0x82, 0x89, 0x20, 0xc0, 0x00, 0x80, 0x10, 0x00, 0x80, 0x00, 0x40, 0xe1, 0x00, 0x00, 0x00, 0x3f, 0x01, 0x00, 0x47, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x47, 0x47, 0x47, 0x47, 0x47, 0x07, 0x47, 0x47, 0x47, 0x47, 0x47, 0x07, 0x47, 0x47, 0x07, 0x07, 0x47, 0x07, 0x47, 0x07, 0x47, 0x47, 0x47, 0x07, 0x07, 0x47, 0x07, 0x07, 0x47, 0x47, 0x07, 0x07, 0x05, 0x45, 0x47, 0x47, 0x47, 0x07, 0x45, 0x47, 0x07, 0x47, 0x07, 0x07, 0x07, 0x07, 0x47, 0x07, 0x47, 0x07, 0x07, 0x07, 0x05, 0x45, 0x45, 0x45, 0x05, 0x05, 0x45, 0x05, 0x45, 0x45, 0x05, 0x05, 0x05, 0x05, 0x45, 0x45, 0x45, 0x45, 0x05, 0x07, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x45, 0x45, 0x05, 0x45, 0x45, 0x05, 0x45, 0x45, 0x05, 0x45, 0x05, 0x45, 0x07, 0x78, 0x41, 0xa6, 0xe6, 0x66, 0x00, 0x78, 0x41, 0x9e, 0xde, 0x5e, 0x00, 0xfe, 0x42, 0x9e, 0xde, 0x5e, 0x00, 0xfe, 0x42, 0x96, 0xd6, 0x56, 0x00, 0x82, 0x43, 0x9e, 0xde, 0x5e, 0x00, 0x82, 0x43, 0x96, 0xd6, 0x56, 0x00, 0xac, 0x46, 0xa6, 0xe6, 0x66, 0x00, 0xac, 0x46, 0x9e, 0xde, 0x5e, 0x00, 0xdb, 0x48, 0xbe, 0xfe, 0x7e, 0x00, 0xdb, 0x48, 0xb6, 0xf6, 0x76, 0x00, 0xe8, 0x49, 0xa6, 0xe6, 0x66, 0x00, 0xe8, 0x49, 0x9e, 0xde, 0x5e, 0x00, 0x25, 0x4e, 0xbe, 0xfe, 0x7e, 0x00, 0x25, 0x4e, 0xb6, 0xf6, 0x76, 0x00, 0x53, 0x4e, 0xbe, 0xfe, 0x7e, 0x00, 0x53, 0x4e, 0xb6, 0xf6, 0x76, 0x00, 0x8e, 0x56, 0x8e, 0xce, 0x4e, 0x00, 0x8e, 0x56, 0x86, 0xc6, 0x46, 0x00, 0xa1, 0x56, 0xa6, 0xe6, 0x66, 0x00, 0xa1, 0x56, 0x9e, 0xde, 0x5e, 0x00, 0x78, 0x42, 0xa6, 0xe6, 0x66, 0x00, 0x78, 0x42, 0x9e, 0xde, 0x5e, 0x00, 0xfe, 0x43, 0x9e, 0xde, 0x5e, 0x00, 0xfe, 0x43, 0x96, 0xd6, 0x56, 0x00, 0x82, 0x44, 0x9e, 0xde, 0x5e, 0x00, 0x82, 0x44, 0x96, 0xd6, 0x56, 0x00, 0xac, 0x47, 0xa6, 0xe6, 0x66, 0x00, 0xac, 0x47, 0x9e, 0xde, 0x5e, 0x00, 0xdb, 0x49, 0xbe, 0xfe, 0x7e, 0x00, 0xdb, 0x49, 0xb6, 0xf6, 0x76, 0x00, 0xe8, 0x4a, 0xa6, 0xe6, 0x66, 0x00, 0xe8, 0x4a, 0x9e, 0xde, 0x5e, 0x00, 0x25, 0x4f, 0xbe, 0xfe, 0x7e, 0x00, 0x25, 0x4f, 0xb6, 0xf6, 0x76, 0x00, 0x53, 0x4f, 0xbe, 0xfe, 0x7e, 0x00, 0x53, 0x4f, 0xb6, 0xf6, 0x76, 0x00, 0x8e, 0x57, 0x8e, 0xce, 0x4e, 0x00, 0x8e, 0x57, 0x86, 0xc6, 0x46, 0x00, 0xa1, 0x57, 0xa6, 0xe6, 0x66, 0x00, 0xa1, 0x57, 0x9e, 0xde, 0x5e, 0x00, 0xad, 0x43, 0x8e, 0xce, 0x4e, 0x00, 0xe2, 0x43, 0xb6, 0xf6, 0x76, 0x00, 0xea, 0x43, 0xa6, 0xe6, 0x66, 0x00, 0x46, 0x44, 0xbe, 0xfe, 0x7e, 0x00, 0x2f, 0x48, 0x86, 0xc6, 0x46, 0x00, 0xa7, 0x49, 0x9e, 0xde, 0x5e, 0x00, 0xea, 0x49, 0x8e, 0xce, 0x4e, 0x00, 0x6c, 0x4a, 0xb6, 0xf6, 0x76, 0x00, 0xb4, 0x4b, 0x8e, 0xce, 0x4e, 0x00, 0xe3, 0x4b, 0x86, 0xc6, 0x46, 0x00, 0x3a, 0x4d, 0xbe, 0xfe, 0x7e, 0x00, 0x80, 0x4d, 0x96, 0xd6, 0x56, 0x00, 0x9d, 0x4d, 0x86, 0xc6, 0x46, 0x00, 0xb0, 0x4d, 0x96, 0xd6, 0x56, 0x00, 0xd2, 0x52, 0x86, 0xc6, 0x46, 0x00, 0x2d, 0x53, 0xae, 0xee, 0x6e, 0x00, 0x32, 0x53, 0x9e, 0xde, 0x5e, 0x00, 0x17, 0x54, 0xa6, 0xe6, 0x66, 0x00, 0x9c, 0x55, 0xb6, 0xf6, 0x76, 0x00, 0x89, 0x57, 0xb6, 0xf6, 0x76, 0x00, 0x2c, 0x40, 0x06, 0x48, 0xd4, 0x78, 0x49, 0x50, 0x07, 0x06, 0x46, 0x06, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc3, 0x59, 0xeb, 0xc3, 0xda, 0xeb, 0xc3, 0x44, 0xed, 0xf3, 0x2a, 0x35, 0xf0, 0x22, 0x60, 0xec, 0x2a, 0x37, 0xf0, 0x22, 0x74, 0xec, 0x2a, 0x39, 0xf0, 0x22, 0x88, 0xec, 0x3e, 0x01, 0x32, 0x62, 0xec, 0x32, 0x76, 0xec, 0x32, 0x8a, 0xec, 0x3e, 0x08, 0x32, 0x63, 0xec, 0x32, 0x77, 0xec, 0x32, 0x8b, 0xec, 0x21, 0x20, 0xec, 0x11, 0x20, 0x00, 0x22, 0xfa, 0xeb, 0x19, 0x22, 0xfc, 0xeb, 0x19, 0x22, 0xfe, 0xeb, 0x21, 0x00, 0x00, 0x22, 0x6e, 0xec, 0x22, 0x82, 0xec, 0x22, 0x96, 0xec, 0x22, 0x70, 0xec, 0x22, 0x84, 0xec, 0x22, 0x98, 0xec, 0xaf, 0x32, 0xf4, 0xeb, 0xc9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0xff, 0x16, 0x07, 0xcd, 0x9b, 0xed, 0xcd, 0x85, 0xed, 0x00, 0xc9, 0xe3, 0xff, 0xf6, 0x03, 0xbd, 0x00, 0x0d, 0xff, 0x0a, 0x0d, 0x0a, 0x00, 0x00, 0x00, 0x0d, 0x03, 0x4f, 0x69, 0x5c, 0xc4, 0x16, 0xc4, 0x3c, 0xc4, 0x5c, 0xc4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x94, 0xc7, 0x1c, 0xd8, 0x94, 0xc7, 0x94, 0xc7, 0x16, 0x95, 0xd7, 0xc7, 0xb5, 0xc6, 0x68, 0xaa, 0x5a, 0xaa, 0xfe, 0x07, 0x58, 0xaa, 0xfe, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x94, 0xc7, 0x1c, 0xd8, 0x94, 0xc7, 0xb5, 0xc6, 0xb5, 0xc6, 0x63, 0x8c, 0x94, 0xc7, 0xb5, 0xc6, 0x05, 0xab, 0xe6, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x94, 0xc7, 0x94, 0xc7, 0x00, 0x94, 0x94, 0xc7, 0x94, 0xc7, 0x57, 0x89, 0x94, 0xc7, 0x57, 0x89, 0xb5, 0xc6, 0xc5, 0xab, 0xe6, 0x02, 0xfa, 0xaa, 0x05, 0x01, 0xd4, 0xaa, 0x01, 0xe3, 0xff, 0x0a, 0xcc, 0xaa, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4d, 0x0f, 0x09, 0xab, 0x0f, 0x08, 0x9d, 0xab, 0x01, 0xf6, 0x03, 0x0d, 0x97, 0xab, 0xa7, 0xab, 0x00, 0x00, 0xa2, 0xab, 0x19, 0x08, 0xcf, 0xab, 0x05, 0x08, 0xd0, 0xad, 0x01, 0xbd, 0x00, 0x0a, 0xc4, 0xad, 0xda, 0xad, 0x00, 0x00, 0xd5, 0xad, 0x36, 0x04, 0xbf, 0x0f, 0xdc, 0x0e, 0x07, 0x0e, 0x3d, 0x0d, 0x7f, 0x0c, 0xcc, 0x0b, 0x22, 0x0b, 0x82, 0x0a, 0xeb, 0x09, 0x5d, 0x09, 0xd6, 0x08, 0x57, 0x08, 0xdf, 0x07, 0x6e, 0x07, 0x03, 0x07, 0x9f, 0x06, 0x40, 0x06, 0xe6, 0x05, 0x91, 0x05, 0x41, 0x05, 0xf6, 0x04, 0xae, 0x04, 0x6b, 0x04, 0x2c, 0x04, 0xf0, 0x03, 0xb7, 0x03, 0x82, 0x03, 0x4f, 0x03, 0x20, 0x03, 0xf3, 0x02, 0xc8, 0x02, 0xa1, 0x02, 0x7b, 0x02, 0x57, 0x02, 0x36, 0x02, 0x16, 0x02, 0xf8, 0x01, 0xdc, 0x01, 0xc1, 0x01, 0xa8, 0x01, 0x90, 0x01, 0x79, 0x01, 0x64, 0x01, 0x50, 0x01, 0x3d, 0x01, 0x2c, 0x01, 0x1b, 0x01, 0x0b, 0x01, 0xfc, 0x00, 0xee, 0x00, 0xe0, 0x00, 0xd4, 0x00, 0xc8, 0x00, 0xbd, 0x00, 0xb2, 0x00, 0xa8, 0x00, 0x9f, 0x00, 0x96, 0x00, 0x8d, 0x00, 0x85, 0x00, 0x7e, 0x00, 0x77, 0x00, 0x70, 0x00, 0x6a, 0x00, 0x64, 0x00, 0x5e, 0x00, 0x59, 0x00, 0x54, 0x00, 0x4f, 0x00, 0x4b, 0x00, 0x47, 0x00, 0x43, 0x00, 0x3f, 0x00, 0x3b, 0x00, 0x38, 0x00, 0x35, 0x00, 0x32, 0x00, 0x2f, 0x00, 0x2d, 0x00, 0x2a, 0x00, 0x28, 0x00, 0x25, 0x00, 0x23, 0x00, 0x21, 0x00, 0xdd, 0x21, 0x60, 0xec, 0x2a, 0xfa, 0xeb, 0x3e, 0x01, 0xcd, 0xb0, 0xed, 0x22, 0xfa, 0xeb, 0xdd, 0x21, 0x74, 0xec, 0x2a, 0xfc, 0xeb, 0x3e, 0x02, 0xcd, 0xb0, 0xed, 0x22, 0xfc, 0xeb, 0xdd, 0x21, 0x88, 0xec, 0x2a, 0xfe, 0xeb, 0x3e, 0x03, 0xcd, 0xb0, 0xed, 0x22, 0xfe, 0xeb, 0x3a, 0x8b, 0xec, 0x07, 0x47, 0x3a, 0x77, 0xec, 0xb0, 0x07, 0x47, 0x3a, 0x63, 0xec, 0xb0, 0x16, 0x07, 0xcd, 0x9b, 0xed, 0x16, 0x0d, 0x21, 0xf3, 0xeb, 0x7a, 0x01, 0xfd, 0xff, 0xed, 0x79, 0x7e, 0x06, 0xbf, 0xed, 0x79, 0x2b, 0x15, 0xf2, 0x8a, 0xed, 0xc9, 0x01, 0xe6, 0xeb, 0x6a, 0x26, 0x00, 0x09, 0x77, 0xc9, 0xed, 0x73, 0xf8, 0xeb, 0x2a, 0xf8, 0xeb, 0xed, 0x7b, 0xf6, 0xeb, 0xc9, 0xed, 0x73, 0xf6, 0xeb, 0xf9, 0x32, 0xf5, 0xeb, 0xdd, 0x35, 0x02, 0xca, 0xbf, 0xee, 0xdd, 0x35, 0x06, 0x20, 0x36, 0xdd, 0x6e, 0x04, 0xdd, 0x66, 0x05, 0x7e, 0xfe, 0x80, 0x20, 0x0c, 0x23, 0x5e, 0x23, 0x56, 0xdd, 0x73, 0x04, 0xdd, 0x72, 0x05, 0x18, 0xe9, 0xfe, 0x1e, 0x38, 0x0c, 0xd6, 0x32, 0xdd, 0x77, 0x09, 0xdd, 0x36, 0x06, 0x01, 0x23, 0x18, 0x09, 0xdd, 0x77, 0x09, 0x23, 0x7e, 0xdd, 0x77, 0x06, 0x23, 0xdd, 0x75, 0x04, 0xdd, 0x74, 0x05, 0xdd, 0x7e, 0x07, 0xdd, 0xb6, 0x08, 0xca, 0x82, 0xee, 0xdd, 0xcb, 0x0e, 0x56, 0xc2, 0x82, 0xee, 0xdd, 0x6e, 0x0c, 0xdd, 0x66, 0x0d, 0x7e, 0x23, 0xdd, 0x75, 0x0c, 0xdd, 0x74, 0x0d, 0xfe, 0x80, 0x20, 0x06, 0x7e, 0x23, 0x66, 0x6f, 0x18, 0xee, 0xfe, 0x82, 0xc2, 0x2d, 0xee, 0xdd, 0xcb, 0x0e, 0xde, 0xc3, 0x0f, 0xee, 0xfe, 0x83, 0xc2, 0x39, 0xee, 0xdd, 0xcb, 0x0e, 0x9e, 0xc3, 0x0f, 0xee, 0xfe, 0x84, 0xc2, 0x49, 0xee, 0x3e, 0x09, 0xdd, 0xae, 0x03, 0xdd, 0x77, 0x03, 0xc3, 0x0f, 0xee, 0xdd, 0xcb, 0x0e, 0x5e, 0xca, 0x6b, 0xee, 0xdd, 0x86, 0x12, 0xdd, 0x77, 0x12, 0x3d, 0x87, 0x5f, 0x16, 0x00, 0x21, 0x9c, 0xec, 0x19, 0x7e, 0xdd, 0x77, 0x07, 0x23, 0x7e, 0xdd, 0x77, 0x08, 0xc3, 0x82, 0xee, 0x5f, 0x16, 0x00, 0xdd, 0x6e, 0x07, 0xdd, 0x66, 0x08, 0xe6, 0x80, 0xca, 0x7b, 0xee, 0x16, 0xff, 0x19, 0xdd, 0x75, 0x07, 0xdd, 0x74, 0x08, 0x3a, 0xf4, 0xeb, 0x16, 0x06, 0xcd, 0x9b, 0xed, 0xdd, 0xcb, 0x0e, 0x96, 0x3a, 0xf5, 0xeb, 0xc6, 0x07, 0x57, 0xdd, 0x7e, 0x07, 0xdd, 0xb6, 0x08, 0x28, 0x03, 0xdd, 0x7e, 0x09, 0xcd, 0x9b, 0xed, 0x3a, 0xf5, 0xeb, 0x3d, 0x87, 0x57, 0xdd, 0x7e, 0x07, 0xcd, 0x9b, 0xed, 0x14, 0xdd, 0x7e, 0x08, 0xcd, 0x9b, 0xed, 0xc3, 0xa4, 0xed, 0xdd, 0x75, 0x00, 0xdd, 0x74, 0x01, 0xc9, 0xdd, 0x6e, 0x00, 0xdd, 0x66, 0x01, 0x7e, 0x23, 0xcd, 0xb8, 0xee, 0xcb, 0x7f, 0xc2, 0x3c, 0xef, 0x22, 0xf8, 0xeb, 0xb7, 0x28, 0x1b, 0xdd, 0x86, 0x0f, 0xdd, 0x77, 0x12, 0xdd, 0xcb, 0x0e, 0x9e, 0x3d, 0x87, 0x5f, 0x16, 0x00, 0x21, 0x9c, 0xec, 0x19, 0x5e, 0x23, 0x56, 0x2a, 0xf8, 0xeb, 0x18, 0x03, 0x11, 0x00, 0x00, 0x7e, 0x23, 0xcd, 0xb8, 0xee, 0xdd, 0x77, 0x02, 0xdd, 0x73, 0x07, 0xdd, 0x72, 0x08, 0xdd, 0x7e, 0x10, 0xdd, 0x77, 0x0c, 0xdd, 0x7e, 0x11, 0xdd, 0x77, 0x0d, 0xdd, 0xcb, 0x0e, 0xd6, 0xdd, 0xcb, 0x0e, 0x4e, 0xc2, 0xbe, 0xed, 0xdd, 0xcb, 0x0e, 0x46, 0xca, 0x23, 0xef, 0xdd, 0xcb, 0x0e, 0xce, 0xdd, 0x4e, 0x0a, 0xdd, 0x46, 0x0b, 0x0a, 0xdd, 0x77, 0x09, 0x03, 0x0a, 0x03, 0xdd, 0x77, 0x06, 0xdd, 0x71, 0x04, 0xdd, 0x70, 0x05, 0xc3, 0x82, 0xee, 0xe6, 0x7f, 0x22, 0xf8, 0xeb, 0x87, 0x5f, 0x16, 0x00, 0x21, 0x52, 0xef, 0x19, 0x7e, 0x23, 0x66, 0x6f, 0xe5, 0x2a, 0xf8, 0xeb, 0xc9, 0x70, 0xef, 0x7c, 0xef, 0x8a, 0xef, 0x94, 0xef, 0xa6, 0xef, 0xb1, 0xef, 0xde, 0xef, 0xbc, 0xef, 0xcc, 0xef, 0xd7, 0xef, 0xee, 0xef, 0xfc, 0xef, 0x0a, 0xf0, 0x17, 0xf0, 0x27, 0xf0, 0x7e, 0xdd, 0x77, 0x00, 0x23, 0x7e, 0xdd, 0x77, 0x01, 0xc3, 0xbf, 0xee, 0x7e, 0xdd, 0x77, 0x00, 0x23, 0x7e, 0xdd, 0x77, 0x01, 0x23, 0xe5, 0xc3, 0xbf, 0xee, 0x46, 0xc5, 0x23, 0xe5, 0xcd, 0xb8, 0xee, 0xc3, 0xbf, 0xee, 0xd1, 0xc1, 0x10, 0x03, 0xc3, 0xbf, 0xee, 0xc5, 0xd5, 0xdd, 0x73, 0x00, 0xdd, 0x72, 0x01, 0xc3, 0xbf, 0xee, 0x7e, 0x23, 0x32, 0xf4, 0xeb, 0xcd, 0xb8, 0xee, 0xc3, 0xbf, 0xee, 0x7e, 0x23, 0xcd, 0xb8, 0xee, 0xdd, 0x77, 0x03, 0xc3, 0xbf, 0xee, 0x7e, 0xdd, 0x77, 0x0a, 0x23, 0x7e, 0xdd, 0x77, 0x0b, 0x23, 0xcd, 0xb8, 0xee, 0xc3, 0xbf, 0xee, 0x7e, 0x23, 0xcd, 0xb8, 0xee, 0xdd, 0x77, 0x0f, 0xc3, 0xbf, 0xee, 0xe1, 0xcd, 0xb8, 0xee, 0xc3, 0xbf, 0xee, 0x7e, 0xdd, 0x77, 0x10, 0x23, 0x7e, 0xdd, 0x77, 0x11, 0x23, 0xcd, 0xb8, 0xee, 0xc3, 0xbf, 0xee, 0xdd, 0xcb, 0x0e, 0xc6, 0xdd, 0xcb, 0x0e, 0x8e, 0xcd, 0xb8, 0xee, 0xc3, 0xbf, 0xee, 0xdd, 0xcb, 0x0e, 0x86, 0xdd, 0xcb, 0x0e, 0x8e, 0xcd, 0xb8, 0xee, 0xc3, 0xbf, 0xee, 0x5e, 0x23, 0x56, 0x23, 0xcd, 0xb8, 0xee, 0x01, 0xbf, 0xee, 0xc5, 0xd5, 0xc9, 0x3a, 0xf4, 0xeb, 0x86, 0xe6, 0x0f, 0x32, 0xf4, 0xeb, 0x23, 0xcd, 0xb8, 0xee, 0xc3, 0xbf, 0xee, 0x7e, 0xdd, 0x86, 0x0f, 0xdd, 0x77, 0x0f, 0x23, 0xcd, 0xb8, 0xee, 0xc3, 0xbf, 0xee, 0x99, 0xf5, 0x96, 0xf4, 0x3b, 0xf0, 0x82, 0x04, 0x81, 0x57, 0xf4, 0x83, 0x81, 0x6d, 0xf3, 0x81, 0x6d, 0xf3, 0x81, 0x00, 0xf4, 0x81, 0x33, 0xf3, 0x81, 0x33, 0xf3, 0x81, 0x17, 0xf3, 0x81, 0x6a, 0xf2, 0x81, 0x6a, 0xf2, 0x88, 0x00, 0x81, 0xba, 0xf2, 0x81, 0xba, 0xf2, 0x88, 0x02, 0x81, 0xba, 0xf2, 0x88, 0x00, 0x81, 0xef, 0xf2, 0x82, 0x04, 0x81, 0x49, 0xf2, 0x83, 0x81, 0x17, 0xf3, 0x81, 0x49, 0xf2, 0x81, 0x49, 0xf2, 0x81, 0x1a, 0xf3, 0x81, 0x49, 0xf2, 0x87, 0x4f, 0xf7, 0x86, 0x5e, 0xf7, 0x2b, 0x23, 0x86, 0x9b, 0xf7, 0x2b, 0x0c, 0x86, 0x5e, 0xf7, 0x2d, 0x48, 0x2b, 0x0c, 0x2d, 0x0c, 0x32, 0x0c, 0x30, 0x0c, 0x2d, 0x18, 0x30, 0x24, 0x86, 0x9b, 0xf7, 0x30, 0x0c, 0x86, 0x5e, 0xf7, 0x32, 0x48, 0x32, 0x0c, 0x37, 0x0c, 0x36, 0x0c, 0x32, 0x0c, 0x2d, 0x18, 0x2b, 0x24, 0x86, 0x9b, 0xf7, 0x2b, 0x0c, 0x86, 0x5e, 0xf7, 0x2d, 0x48, 0x32, 0x0c, 0x86, 0x97, 0xf7, 0x32, 0x0c, 0x86, 0x5e, 0xf7, 0x32, 0x0c, 0x30, 0x0c, 0x2d, 0x18, 0x32, 0x24, 0x86, 0x97, 0xf7, 0x32, 0x0c, 0x86, 0x5e, 0xf7, 0x30, 0x48, 0x32, 0x0c, 0x34, 0x0c, 0x37, 0x0c, 0x36, 0x0c, 0x37, 0x0c, 0x39, 0x0c, 0x37, 0x24, 0x86, 0x9b, 0xf7, 0x37, 0x0c, 0x86, 0x5e, 0xf7, 0x39, 0x30, 0x37, 0x06, 0x39, 0x0c, 0x37, 0x06, 0x39, 0x0c, 0x37, 0x06, 0x36, 0x0c, 0x37, 0x06, 0x36, 0x0c, 0x34, 0x0c, 0x32, 0x0c, 0x30, 0x06, 0x32, 0x0c, 0x30, 0x06, 0x32, 0x0c, 0x30, 0x06, 0x2f, 0x0c, 0x30, 0x06, 0x2f, 0x0c, 0x2d, 0x0c, 0x2b, 0x0c, 0x2d, 0x06, 0x2d, 0x0c, 0x2b, 0x06, 0x2d, 0x0c, 0x2f, 0x06, 0x30, 0x0c, 0x32, 0x06, 0x34, 0x0c, 0x36, 0x0c, 0x37, 0x0c, 0x3b, 0x24, 0x86, 0x97, 0xf7, 0x3b, 0x0c, 0x86, 0x5e, 0xf7, 0x39, 0x48, 0x37, 0x0c, 0x39, 0x0c, 0x3c, 0x06, 0x3c, 0x06, 0x39, 0x0c, 0x3e, 0x0c, 0x3c, 0x0c, 0x40, 0x24, 0x86, 0x97, 0xf7, 0x40, 0x0c, 0x86, 0x5e, 0xf7, 0x3e, 0x60, 0x00, 0x06, 0x3e, 0x06, 0x3e, 0x06, 0x40, 0x06, 0x41, 0x06, 0x40, 0x06, 0x3c, 0x06, 0x3e, 0x07, 0x81, 0xd9, 0xf1, 0x81, 0x11, 0xf2, 0x82, 0x02, 0x3d, 0x0b, 0x36, 0x0c, 0x3b, 0x0c, 0x36, 0x06, 0x3a, 0x0c, 0x36, 0x06, 0x38, 0x0c, 0x36, 0x06, 0x36, 0x06, 0x3b, 0x06, 0x3d, 0x06, 0x3d, 0x06, 0x3d, 0x06, 0x36, 0x0c, 0x3b, 0x0c, 0x36, 0x06, 0x3a, 0x0c, 0x36, 0x06, 0x38, 0x0c, 0x36, 0x06, 0x36, 0x06, 0x3b, 0x06, 0x3d, 0x07, 0x83, 0x81, 0x6a, 0xf2, 0x81, 0x49, 0xf2, 0x81, 0xc3, 0xf1, 0x81, 0x1a, 0xf3, 0x81, 0x4c, 0xf2, 0x81, 0xba, 0xf2, 0x81, 0x4c, 0xf2, 0x88, 0x02, 0x81, 0xba, 0xf2, 0x88, 0x00, 0x81, 0xef, 0xf2, 0x81, 0x4c, 0xf2, 0x81, 0xc3, 0xf1, 0x80, 0x3b, 0xf0, 0x87, 0xff, 0xf6, 0x46, 0x18, 0x00, 0x30, 0x87, 0x33, 0xf7, 0x86, 0x1b, 0xf7, 0x28, 0x0b, 0x00, 0x01, 0x28, 0x0b, 0x00, 0x01, 0x89, 0x87, 0x4f, 0xf7, 0x86, 0x5e, 0xf7, 0x82, 0x02, 0x40, 0x0b, 0x39, 0x0c, 0x3e, 0x0c, 0x39, 0x06, 0x3c, 0x0c, 0x39, 0x06, 0x3b, 0x0c, 0x3c, 0x06, 0x39, 0x06, 0x3c, 0x06, 0x3e, 0x06, 0x40, 0x06, 0x40, 0x06, 0x39, 0x0c, 0x3e, 0x0c, 0x39, 0x06, 0x3c, 0x0c, 0x39, 0x06, 0x3b, 0x0c, 0x3c, 0x06, 0x39, 0x06, 0x3c, 0x06, 0x3e, 0x07, 0x83, 0x89, 0x87, 0x4f, 0xf7, 0x86, 0x5e, 0xf7, 0x82, 0x02, 0x40, 0x0b, 0x39, 0x0c, 0x3f, 0x0c, 0x39, 0x06, 0x3d, 0x0c, 0x3d, 0x06, 0x3b, 0x0c, 0x3d, 0x06, 0x39, 0x06, 0x3d, 0x06, 0x3f, 0x06, 0x40, 0x06, 0x40, 0x06, 0x39, 0x0c, 0x3f, 0x0c, 0x39, 0x06, 0x3d, 0x0c, 0x3d, 0x06, 0x3b, 0x0c, 0x3d, 0x06, 0x39, 0x06, 0x3d, 0x06, 0x3f, 0x07, 0x83, 0x89, 0x81, 0x4c, 0xf2, 0x86, 0x45, 0xf7, 0x87, 0x9f, 0xf7, 0x82, 0x04, 0x46, 0x06, 0x83, 0x46, 0x0c, 0x44, 0x06, 0x46, 0x0a, 0x00, 0x02, 0x44, 0x06, 0x46, 0x0a, 0x00, 0x02, 0x46, 0x0c, 0x44, 0x0c, 0x89, 0x87, 0x4f, 0xf7, 0x86, 0x5e, 0xf7, 0x36, 0x23, 0x86, 0x97, 0xf7, 0x36, 0x0c, 0x86, 0x5e, 0xf7, 0x34, 0x18, 0x31, 0x0c, 0x2f, 0x18, 0x2e, 0x0c, 0x2e, 0x0c, 0x81, 0xef, 0xf3, 0x8e, 0xfd, 0x81, 0xef, 0xf3, 0x8e, 0x03, 0x87, 0x4f, 0xf7, 0x86, 0x5e, 0xf7, 0x2e, 0x0c, 0x2f, 0x0c, 0x31, 0x0c, 0x31, 0x12, 0x31, 0x12, 0x31, 0x0c, 0x34, 0x12, 0x31, 0x12, 0x2f, 0x0c, 0x31, 0x18, 0x86, 0x97, 0xf7, 0x31, 0x30, 0x81, 0xef, 0xf3, 0x8e, 0xfd, 0x81, 0xef, 0xf3, 0x00, 0x01, 0x8e, 0x03, 0x89, 0x87, 0x4f, 0xf7, 0x86, 0x5e, 0xf7, 0x32, 0x18, 0x81, 0xef, 0xf3, 0x87, 0x4f, 0xf7, 0x86, 0x5e, 0xf7, 0x32, 0x06, 0x32, 0x06, 0x34, 0x12, 0x32, 0x12, 0x30, 0x0c, 0x32, 0x18, 0x81, 0xef, 0xf3, 0x8e, 0xfb, 0x81, 0xef, 0xf3, 0x81, 0x87, 0xf5, 0x86, 0x1b, 0xf7, 0x87, 0x33, 0xf7, 0x8e, 0x05, 0x2b, 0x0c, 0x28, 0x0c, 0x89, 0x87, 0x4f, 0xf7, 0x86, 0x5e, 0xf7, 0x34, 0x18, 0x81, 0xef, 0xf3, 0x87, 0x4f, 0xf7, 0x86, 0x5e, 0xf7, 0x34, 0x06, 0x34, 0x06, 0x36, 0x12, 0x34, 0x12, 0x32, 0x0c, 0x34, 0x12, 0x36, 0x12, 0x38, 0x0c, 0x36, 0x12, 0x38, 0x12, 0x39, 0x0c, 0x89, 0x81, 0x1a, 0xf3, 0x87, 0x4f, 0xf7, 0x86, 0x5e, 0xf7, 0x82, 0x02, 0x82, 0x02, 0x30, 0x06, 0x2f, 0x0c, 0x2e, 0x06, 0x2d, 0x0c, 0x83, 0x30, 0x0c, 0x32, 0x0c, 0x83, 0x89, 0x87, 0x4f, 0xf7, 0x86, 0x7c, 0xf7, 0x82, 0x04, 0x30, 0x06, 0x2f, 0x0c, 0x2e, 0x06, 0x2d, 0x0c, 0x83, 0x30, 0x06, 0x2f, 0x0c, 0x2d, 0x06, 0x35, 0x0c, 0x34, 0x0c, 0x82, 0x02, 0x35, 0x06, 0x34, 0x0c, 0x33, 0x06, 0x32, 0x0c, 0x83, 0x35, 0x0c, 0x34, 0x0c, 0x82, 0x02, 0x2f, 0x06, 0x2e, 0x0c, 0x2d, 0x06, 0x2c, 0x0c, 0x83, 0x30, 0x0c, 0x2f, 0x0c, 0x89, 0x87, 0x4f, 0xf7, 0x86, 0x5e, 0xf7, 0x88, 0x00, 0x00, 0x05, 0x2d, 0x06, 0x2d, 0x0c, 0x2d, 0x0c, 0x2d, 0x0c, 0x2d, 0x18, 0x2d, 0x1e, 0x2d, 0x06, 0x34, 0x0c, 0x34, 0x0c, 0x34, 0x0c, 0x34, 0x18, 0x81, 0xef, 0xf3, 0x00, 0x0c, 0x35, 0x18, 0x34, 0x18, 0x35, 0x18, 0x34, 0x0c, 0x32, 0x12, 0x2f, 0x06, 0x2f, 0x0c, 0x2f, 0x0c, 0x2f, 0x0c, 0x2f, 0x18, 0x81, 0xef, 0xf3, 0x00, 0x0c, 0x00, 0x06, 0x30, 0x06, 0x30, 0x0c, 0x30, 0x0c, 0x30, 0x0c, 0x30, 0x18, 0x30, 0x1e, 0x30, 0x06, 0x37, 0x0c, 0x37, 0x0c, 0x37, 0x0c, 0x37, 0x18, 0x81, 0xef, 0xf3, 0x00, 0x0c, 0x38, 0x18, 0x37, 0x18, 0x38, 0x18, 0x37, 0x0c, 0x35, 0x12, 0x32, 0x06, 0x32, 0x0c, 0x32, 0x0c, 0x32, 0x0c, 0x32, 0x18, 0x87, 0x33, 0xf7, 0x86, 0x1b, 0xf7, 0x00, 0x01, 0x2d, 0x0b, 0x00, 0x01, 0x28, 0x05, 0x00, 0x01, 0x28, 0x06, 0x89, 0x87, 0x33, 0xf7, 0x86, 0x1b, 0xf7, 0x00, 0x01, 0x2b, 0x0b, 0x87, 0x4f, 0xf7, 0x86, 0x5e, 0xf7, 0x89, 0x87, 0x69, 0xf7, 0x84, 0x1f, 0x85, 0x01, 0x82, 0x04, 0x07, 0x06, 0x8d, 0xfe, 0x83, 0x85, 0x08, 0x87, 0x4f, 0xf7, 0x86, 0x5e, 0xf7, 0x2d, 0x0b, 0x2d, 0x0c, 0x2d, 0x06, 0x2d, 0x06, 0x2d, 0x0c, 0x2f, 0x0c, 0x30, 0x0c, 0x32, 0x06, 0x32, 0x06, 0x32, 0x0c, 0x32, 0x0c, 0x32, 0x0c, 0x32, 0x18, 0x81, 0xef, 0xf3, 0x32, 0x06, 0x34, 0x06, 0x35, 0x06, 0x35, 0x06, 0x34, 0x0c, 0x32, 0x0c, 0x30, 0x0c, 0x2f, 0x0c, 0x2d, 0x0c, 0x2c, 0x1e, 0x2d, 0x06, 0x2d, 0x0c, 0x2d, 0x0c, 0x2f, 0x0c, 0x2d, 0x18, 0x81, 0xef, 0xf3, 0x00, 0x0d, 0x89, 0x88, 0x07, 0x87, 0x3e, 0xf7, 0x86, 0x45, 0xf7, 0x45, 0x04, 0x00, 0x02, 0x45, 0x04, 0x00, 0x02, 0x39, 0x0c, 0x87, 0x1f, 0xf7, 0x86, 0x38, 0xf7, 0x2d, 0x0b, 0x2d, 0x0c, 0x2e, 0x12, 0x2d, 0x12, 0x2b, 0x0c, 0x2b, 0x06, 0x2d, 0x06, 0x2d, 0x06, 0x2d, 0x06, 0x2d, 0x0c, 0x2b, 0x0c, 0x2d, 0x06, 0x2b, 0x06, 0x2d, 0x0d, 0x87, 0x3e, 0xf7, 0x86, 0x45, 0xf7, 0x40, 0x0c, 0x39, 0x0c, 0x89, 0x82, 0x04, 0x81, 0x6e, 0xf5, 0x83, 0x81, 0x60, 0xf5, 0x81, 0x60, 0xf5, 0x82, 0x06, 0x81, 0x6e, 0xf5, 0x83, 0x81, 0x2f, 0xf5, 0x81, 0x2f, 0xf5, 0x8e, 0xf8, 0x81, 0x2c, 0xf5, 0x81, 0x2c, 0xf5, 0x8e, 0x01, 0x81, 0x2c, 0xf5, 0x8e, 0x02, 0x81, 0x2c, 0xf5, 0x8e, 0x05, 0x88, 0xf4, 0x82, 0x04, 0x81, 0x49, 0xf2, 0x83, 0x88, 0x00, 0x81, 0x2f, 0xf5, 0x81, 0x2f, 0xf5, 0x88, 0xf4, 0x81, 0x49, 0xf2, 0x81, 0x49, 0xf2, 0x88, 0x00, 0x81, 0x2f, 0xf5, 0x88, 0xf4, 0x81, 0x49, 0xf2, 0x88, 0x00, 0x82, 0x08, 0x81, 0x2f, 0xf5, 0x83, 0x81, 0x2c, 0xf5, 0x88, 0xf8, 0x81, 0x2c, 0xf5, 0x81, 0x2c, 0xf5, 0x81, 0x2c, 0xf5, 0x88, 0xf4, 0x81, 0x49, 0xf2, 0x88, 0xff, 0x81, 0xc3, 0xf1, 0x88, 0x00, 0x81, 0x2f, 0xf5, 0x81, 0x24, 0xf5, 0x88, 0xf9, 0x81, 0x2f, 0xf5, 0x81, 0x24, 0xf5, 0x88, 0xfb, 0x81, 0x2c, 0xf5, 0x81, 0x24, 0xf5, 0x81, 0xc3, 0xf1, 0x88, 0x00, 0x80, 0x96, 0xf4, 0x88, 0xf4, 0x81, 0x4c, 0xf2, 0x88, 0xff, 0x89, 0x81, 0x2f, 0xf5, 0x87, 0x8c, 0xf7, 0x86, 0x38, 0xf7, 0x43, 0x0c, 0x45, 0x0c, 0x86, 0x84, 0xf7, 0x8e, 0x0c, 0x2d, 0x0c, 0x2d, 0x0c, 0x2d, 0x24, 0x2b, 0x06, 0x2b, 0x0c, 0x2d, 0x06, 0x2d, 0x0c, 0x2d, 0x0c, 0x2b, 0x0c, 0x2d, 0x06, 0x2b, 0x06, 0x2d, 0x0c, 0x8e, 0xf4, 0x86, 0x38, 0xf7, 0x43, 0x0c, 0x45, 0x0c, 0x89, 0x81, 0x6b, 0xf5, 0x8e, 0x03, 0x81, 0x6b, 0xf5, 0x8e, 0xfd, 0x89, 0x81, 0x6e, 0xf5, 0x81, 0x87, 0xf5, 0x34, 0x0c, 0x34, 0x0c, 0x35, 0x12, 0x34, 0x12, 0x32, 0x0c, 0x81, 0x87, 0xf5, 0x34, 0x0c, 0x34, 0x0c, 0x34, 0x18, 0x00, 0x18, 0x89, 0x84, 0x0a, 0x85, 0x01, 0x87, 0x69, 0xf7, 0x86, 0x2b, 0xf7, 0x07, 0x18, 0x85, 0x08, 0x87, 0x1f, 0xf7, 0x89, 0x81, 0xa0, 0xf6, 0x81, 0xa0, 0xf6, 0x81, 0x95, 0xf6, 0x81, 0x95, 0xf6, 0x81, 0xb6, 0xf6, 0x88, 0x05, 0x81, 0xb6, 0xf6, 0x88, 0xfb, 0x81, 0xb6, 0xf6, 0x88, 0x00, 0x81, 0xb6, 0xf6, 0x81, 0xa0, 0xf6, 0x81, 0xa0, 0xf6, 0x81, 0xb3, 0xf6, 0x88, 0x05, 0x81, 0xb3, 0xf6, 0x88, 0xfd, 0x81, 0x8a, 0xf6, 0x81, 0x8a, 0xf6, 0x88, 0x05, 0x81, 0xb0, 0xf6, 0x88, 0xfb, 0x81, 0xb0, 0xf6, 0x88, 0x00, 0x82, 0x04, 0x81, 0x55, 0xf6, 0x83, 0x81, 0xb3, 0xf6, 0x88, 0x05, 0x81, 0xb3, 0xf6, 0x88, 0x00, 0x81, 0x55, 0xf6, 0x81, 0x55, 0xf6, 0x81, 0xb6, 0xf6, 0x88, 0x05, 0x81, 0xb6, 0xf6, 0x88, 0x00, 0x81, 0x55, 0xf6, 0x82, 0x04, 0x88, 0x00, 0x81, 0xb3, 0xf6, 0x88, 0x05, 0x81, 0xb3, 0xf6, 0x83, 0x88, 0x00, 0x81, 0xb3, 0xf6, 0x88, 0x05, 0x81, 0xb3, 0xf6, 0x88, 0x04, 0x81, 0xb3, 0xf6, 0x88, 0x00, 0x81, 0xb3, 0xf6, 0x88, 0xfd, 0x81, 0xb3, 0xf6, 0x88, 0x04, 0x81, 0xb3, 0xf6, 0x88, 0xfd, 0x81, 0x8a, 0xf6, 0x88, 0x00, 0x81, 0x55, 0xf6, 0x00, 0x60, 0x81, 0xb6, 0xf6, 0x88, 0x05, 0x81, 0xb6, 0xf6, 0x81, 0x58, 0xf6, 0x88, 0x05, 0x81, 0xb3, 0xf6, 0x81, 0x58, 0xf6, 0x88, 0xfb, 0x81, 0xb0, 0xf6, 0x81, 0x58, 0xf6, 0x00, 0x60, 0x88, 0x00, 0x80, 0x99, 0xf5, 0x81, 0x58, 0xf6, 0x88, 0x00, 0x86, 0x1b, 0xf7, 0x82, 0x04, 0x81, 0x76, 0xf6, 0x83, 0x2b, 0x09, 0x00, 0x03, 0x82, 0x06, 0x81, 0x76, 0xf6, 0x83, 0x2b, 0x09, 0x00, 0x03, 0x27, 0x09, 0x00, 0x03, 0x89, 0x87, 0x33, 0xf7, 0x85, 0x01, 0x84, 0x1c, 0x07, 0x01, 0x00, 0x01, 0x84, 0x02, 0x07, 0x01, 0x00, 0x03, 0x85, 0x08, 0x89, 0x81, 0xb3, 0xf6, 0x8e, 0x07, 0x81, 0xb3, 0xf6, 0x8e, 0xf9, 0x89, 0x81, 0xa0, 0xf6, 0x8e, 0x03, 0x81, 0xa0, 0xf6, 0x8e, 0xfd, 0x89, 0x81, 0xb3, 0xf6, 0x8e, 0x01, 0x81, 0xb6, 0xf6, 0x8e, 0xfa, 0x81, 0xb6, 0xf6, 0x8e, 0x05, 0x89, 0x81, 0xb3, 0xf6, 0x81, 0xb6, 0xf6, 0x87, 0xeb, 0xf6, 0x86, 0xf4, 0xf6, 0x15, 0x0c, 0x15, 0x06, 0x21, 0x06, 0x81, 0xd1, 0xf6, 0x15, 0x0c, 0x15, 0x18, 0x81, 0xd1, 0xf6, 0x1f, 0x06, 0x21, 0x06, 0x89, 0x87, 0xff, 0xf6, 0x84, 0x1f, 0x85, 0x01, 0x8a, 0x82, 0x06, 0x07, 0x01, 0x8d, 0xf0, 0x07, 0x01, 0x8d, 0x0e, 0x83, 0x8b, 0x85, 0x08, 0x87, 0xeb, 0xf6, 0x89, 0x0f, 0x01, 0x40, 0x3f, 0x0c, 0xff, 0x80, 0xeb, 0xf6, 0x00, 0x00, 0x05, 0x05, 0x03, 0xfd, 0xfb, 0xfb, 0x80, 0xf4, 0xf6, 0x0f, 0x01, 0x40, 0x3b, 0x3f, 0x3e, 0x3b, 0x3d, 0x3c, 0x3b, 0x3b, 0x3a, 0x3b, 0x39, 0x38, 0x3b, 0x37, 0x36, 0x3b, 0x35, 0x34, 0x3b, 0x33, 0x00, 0xff, 0x80, 0xff, 0xf6, 0x32, 0x80, 0x1b, 0xf7, 0x0f, 0x01, 0x40, 0x3f, 0x3e, 0x3d, 0x3a, 0x0b, 0x02, 0x80, 0x25, 0xf7, 0x82, 0x0c, 0xf4, 0x07, 0xf9, 0x80, 0x2b, 0xf7, 0x0f, 0xff, 0x80, 0x33, 0xf7, 0x82, 0x0c, 0xf4, 0x80, 0x38, 0xf7, 0x0f, 0x01, 0x3f, 0x3a, 0x80, 0x3e, 0xf7, 0x82, 0x05, 0x03, 0xf8, 0x05, 0x07, 0xf4, 0x80, 0x45, 0xf7, 0x00, 0x01, 0x0f, 0x03, 0x0e, 0x04, 0x0d, 0x04, 0x0c, 0x04, 0x0b, 0xff, 0x80, 0x4f, 0xf7, 0x02, 0x01, 0xff, 0xfe, 0xfe, 0xff, 0x01, 0x02, 0x80, 0x5e, 0xf7, 0x0f, 0x02, 0x00, 0x04, 0x0e, 0x02, 0x00, 0x04, 0x0d, 0x03, 0x00, 0x03, 0x0c, 0x03, 0x00, 0x03, 0x80, 0x69, 0xf7, 0x83, 0x05, 0x82, 0x18, 0xe8, 0x80, 0x7c, 0xf7, 0x82, 0x00, 0x0c, 0xf4, 0x00, 0x80, 0x84, 0xf7, 0x0e, 0x01, 0x3f, 0x3e, 0x0b, 0x02, 0x0a, 0x02, 0x80, 0x90, 0xf7, 0x02, 0x80, 0x97, 0xf7, 0xfe, 0x80, 0x9b, 0xf7, 0x0e, 0x01, 0x3f, 0x3e, 0x3d, 0x3c, 0x3b, 0x80, 0x9f, 0xf7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; TRDOS_DIR_ELEMENT sbootdir = { {'b','o','o','t',' ',' ',' ',' '}, 'B', 0xB4, 0xB4, (sizeof(sbootimage)+255)/256, 0, 0 }; long CalcCRC32(long CRC, unsigned char Symbol) { long temp; CRC ^= -1l ^ Symbol; for (int k = 8; k--;) { temp = -(CRC & 1), CRC >>= 1, CRC ^= 0xEDB88320ul & temp; } CRC ^= -1l; return CRC; } long filelength(int hfile) { long ret = lseek(hfile, 0, SEEK_END); lseek(hfile, 0, SEEK_SET); return ret; } //---------------------------------------------------------------------------- TDiskImage::TDiskImage() { for (int t = 0; t < 256; t++) for (int s = 0; s < 256; s++) { FTrackLength[t][s] = 0; FTracksPtr[t][s][0] = NULL; FTracksPtr[t][s][1] = NULL; } DiskPresent = false; ReadOnly = true; Changed = false; FType = DIT_UNK; MaxTrack = 81; MaxSide = 0x01; } //----------------------------------------------------------------------------- TDiskImage::~TDiskImage() { ReadOnly = true; DiskPresent = false; Changed = false; FType = DIT_UNK; for (int t = 0; t < 256; t++) for (int s = 0; s < 256; s++) { FTrackLength[t][s] = 0; if (FTracksPtr[t][s][0]) delete FTracksPtr[t][s][0]; FTracksPtr[t][s][0] = NULL; if (FTracksPtr[t][s][1]) delete FTracksPtr[t][s][1]; FTracksPtr[t][s][1] = NULL; } } //----------------------------------------------------------------------------- unsigned short TDiskImage::MakeVGCRC(unsigned char *data, unsigned long length) { unsigned short CRC = 0xFFFF; for (unsigned int i = 0; i < length; i++) { CRC ^= data[i] << 8; for (unsigned int j = 0; j < 8; j++) { if (CRC & 0x8000) CRC = (CRC << 1) ^ 0x1021; else CRC <<= 1; } } return CRC; // H<-->L !!! } //----------------------------------------------------------------------------- void TDiskImage::ApplySectorCRC(VGFIND_SECTOR vgfs) { unsigned char *TrackPtr = vgfs.vgfa.TrackPointer; unsigned int TrackLen = vgfs.vgfa.TrackLength; unsigned int len = vgfs.OffsetEndSector - vgfs.MarkedOffsetSector; if (vgfs.OffsetEndSector < vgfs.MarkedOffsetSector) len = (TrackLen - vgfs.MarkedOffsetSector) + vgfs.OffsetEndSector; unsigned int off1 = vgfs.MarkedOffsetSector; unsigned int len1 = TrackLen - vgfs.MarkedOffsetSector; if (len1 > len) len1 = len; unsigned int off2 = 0; unsigned int len2 = 0; if (len1 < len) len2 = len - len1; unsigned int i; unsigned short CRC = 0xFFFF; for (i = 0; i < len1; i++) { CRC ^= TrackPtr[off1 + i] << 8; for (unsigned int j = 0; j < 8; j++) { if (CRC & 0x8000) CRC = (CRC << 1) ^ 0x1021; else CRC <<= 1; } } for (i = 0; i < len2; i++) { CRC ^= TrackPtr[off2 + i] << 8; for (unsigned int j = 0; j < 8; j++) { if (CRC & 0x8000) CRC = (CRC << 1) ^ 0x1021; else CRC <<= 1; } } unsigned int crcoff = (off1 + len1) % TrackLen; if (len2) crcoff = (off2 + len2) % TrackLen; TrackPtr[crcoff] = (unsigned char)(CRC >> 8); TrackPtr[(crcoff + 1) % TrackLen] = (unsigned char)(CRC & 0xFF); } //----------------------------------------------------------------------------- // // DANGER! CRC checking not prepared for track length overflow! // bool TDiskImage::FindADMark(unsigned char CYL, unsigned char SIDE, unsigned int FromOffset, VGFIND_ADM *vgfa) { vgfa->TrackPointer = NULL; vgfa->ClkPointer = NULL; vgfa->TrackLength = 0; vgfa->ADMPointer = NULL; vgfa->ADMLength = 0; vgfa->FoundADM = false; vgfa->CRCOK = false; if ((!DiskPresent) | ((CYL > MaxTrack) || (SIDE > MaxSide)) | ((!FTracksPtr[CYL][SIDE][0]) || (!FTracksPtr[CYL][SIDE][1]))) { return false; // ERROR: disk not ready } unsigned char *track = vgfa->TrackPointer = FTracksPtr[CYL][SIDE][0]; unsigned char *clks = vgfa->ClkPointer = FTracksPtr[CYL][SIDE][1]; unsigned int tlen = vgfa->TrackLength = FTrackLength[CYL][SIDE]; unsigned int off, rc; unsigned int pos = FromOffset; for (; pos < tlen + FromOffset; pos++) { off = pos%tlen; if ((track[off] == 0xA1) && (clks[off])) // fnd Mark { off = (off + 1) % tlen; rc = tlen; while ((track[off] == 0xA1) && (clks[off])) // repeat Mark { if (!rc) return false; // ERROR: MFM marks all disk off = (off + 1) % tlen; rc--; } if (track[off] != 0xFE) continue; off = (off + 1) % tlen; vgfa->FoundADM = true; vgfa->MarkedOffsetADM = pos%tlen; vgfa->OffsetADM = off; vgfa->OffsetEndADM = (off + 6) % tlen; vgfa->ADMLength = 6; vgfa->ADMPointer = track + off; unsigned short crc = MakeVGCRC(track + (pos%tlen), (off - (pos%tlen)) + 4); vgfa->CRCOK = (track[(off + 4) % tlen] == (crc >> 8)) && (track[(off + 5) % tlen] == (crc & 0xFF)); return true; } } return false; } //----------------------------------------------------------------------------- // // DANGER! CRC checking not prepared for track length overflow! // bool TDiskImage::FindSector(unsigned char CYL, unsigned char SIDE, unsigned char SECT, VGFIND_SECTOR *vgfs, unsigned int FromOffset) { vgfs->SectorPointer = NULL; vgfs->SectorLength = 0; vgfs->FoundDATA = false; vgfs->CRCOK = false; if ((!DiskPresent) | ((CYL > MaxTrack) || (SIDE > MaxSide)) | ((!FTracksPtr[CYL][SIDE][0]) || (!FTracksPtr[CYL][SIDE][1]))) { vgfs->vgfa.TrackPointer = NULL; vgfs->vgfa.ClkPointer = NULL; vgfs->vgfa.TrackLength = 0; vgfs->vgfa.ADMPointer = NULL; vgfs->vgfa.ADMLength = 0; vgfs->vgfa.FoundADM = false; vgfs->vgfa.CRCOK = false; return false; // ERROR: disk not ready } unsigned int TrackOffset = FromOffset; bool FirstFind = true; unsigned int FirstPos = 0; // Поиск адресной метки требуемого сектора... bool ADFOUND = false; for (;;) { if (!FindADMark(CYL, SIDE, TrackOffset, &(vgfs->vgfa))) return false; // ERROR: No ADMARK found on track if (vgfs->vgfa.TrackPointer[(vgfs->vgfa.OffsetADM + 2) % vgfs->vgfa.TrackLength] == SECT) { ADFOUND = true; break; } if (!FirstFind) { if (vgfs->vgfa.OffsetEndADM == FirstPos) break; } else { FirstPos = vgfs->vgfa.OffsetEndADM; FirstFind = false; } TrackOffset = vgfs->vgfa.OffsetEndADM; }; if (!ADFOUND) return false; // ADRMARK нужного найден, поиск массива данных... unsigned char *track = vgfs->vgfa.TrackPointer; unsigned char *clks = vgfs->vgfa.ClkPointer; unsigned int tlen = vgfs->vgfa.TrackLength; unsigned int pos = vgfs->vgfa.OffsetEndADM; unsigned int off, rc; for (; pos < tlen * 2; pos++) { off = pos%tlen; if ((track[off] == 0xA1) && (clks[off])) // fnd Mark { off = (off + 1) % tlen; rc = tlen; while ((track[off] == 0xA1) && (clks[off])) // repeat Mark { if (!rc) return false; // ERROR: MFM marks all disk off = (off + 1) % tlen; rc--; } if ((track[off] < 0xF8) || (track[off] > 0xFB)) { break; // ERROR: data array not found } vgfs->DataMarker = track[off]; off = (off + 1) % tlen; vgfs->FoundDATA = true; unsigned char SL = vgfs->vgfa.TrackPointer[(vgfs->vgfa.OffsetADM + 3) % vgfs->vgfa.TrackLength]; vgfs->SectorLength = 128; if (SL) vgfs->SectorLength <<= SL; vgfs->SectorPointer = track + off; vgfs->MarkedOffsetSector = pos%tlen; vgfs->OffsetSector = off; vgfs->OffsetEndSector = (off + vgfs->SectorLength) % tlen; unsigned short crc = MakeVGCRC(track + (pos%tlen), (off - (pos%tlen)) + vgfs->SectorLength); vgfs->CRCOK = (track[(off + vgfs->SectorLength) % tlen] == (crc >> 8)) && (track[(off + vgfs->SectorLength + 1) % tlen] == (crc & 0xFF)); return true; // OK read } } return false; } //----------------------------------------------------------------------------- bool TDiskImage::FindTrack(unsigned char CYL, unsigned char SIDE, VGFIND_TRACK *vgft) { vgft->FoundTrack = false; vgft->TrackPointer = NULL; vgft->ClkPointer = NULL; vgft->TrackLength = 0; if ((!DiskPresent) | ((CYL > MaxTrack) || (SIDE > MaxSide)) | ((!FTracksPtr[CYL][SIDE][0]) || (!FTracksPtr[CYL][SIDE][1]))) { return false; // ERROR: disk not ready } vgft->TrackPointer = FTracksPtr[CYL][SIDE][0]; vgft->ClkPointer = FTracksPtr[CYL][SIDE][1]; vgft->TrackLength = FTrackLength[CYL][SIDE]; vgft->FoundTrack = true; return true; } //----------------------------------------------------------------------------- void TDiskImage::Open(const char *filename, bool ROnly) { const char *ext = ""; if (strlen(filename) > 4) ext = filename + strlen(filename) - 4; TDiskImageType typ = DIT_UNK; if (!strcasecmp(ext, ".SCL")) typ = DIT_SCL; if (!strcasecmp(ext, ".FDI")) typ = DIT_FDI; if (!strcasecmp(ext, ".UDI")) typ = DIT_UDI; if (!strcasecmp(ext, ".TD0")) typ = DIT_TD0; if (!strcasecmp(ext, ".FDD")) typ = DIT_FDD; if (!memcmp(ext + 1, ".$", 2)) typ = DIT_HOB; if (!memcmp(ext + 1, ".!", 2)) typ = DIT_HOB; if (!((FType == DIT_HOB) && (typ == DIT_HOB))) // if not hobeta clear disk... { ReadOnly = true; DiskPresent = false; Changed = false; FType = DIT_UNK; for (int t = 0; t < 256; t++) for (int s = 0; s < 256; s++) { FTrackLength[t][s] = 0; if (FTracksPtr[t][s][0]) delete FTracksPtr[t][s][0]; FTracksPtr[t][s][0] = NULL; if (FTracksPtr[t][s][1]) delete FTracksPtr[t][s][1]; FTracksPtr[t][s][1] = NULL; } } if (typ == DIT_UNK) { ShowError(ERR_UNKFORMAT); return; } FType = typ; int hfile = open(filename, O_RDONLY); if (hfile < 0) { char sbuf[8192]; sprintf(sbuf, ERR_OPEN" %s", filename); ShowError(sbuf); return; } if (typ == DIT_SCL) readSCL(hfile, ROnly); if (typ == DIT_FDI) readFDI(hfile, ROnly); if (typ == DIT_UDI) readUDI(hfile, ROnly); if (typ == DIT_TD0) readTD0(hfile, ROnly); if (typ == DIT_FDD) readFDD(hfile, ROnly); if (typ == DIT_HOB) readHOB(hfile); close(hfile); } //----------------------------------------------------------------------------- void TDiskImage::formatTRDOS(unsigned int Tcount, unsigned int Scount) { MaxTrack = Tcount - 1; MaxSide = Scount - 1; unsigned short TotalSecs = Tcount*Scount * 16 - 16; // форматирование нового диска под TR-DOS (16 x 256bytes sector per track)... unsigned int ptrcrc; unsigned int r; unsigned short vgcrc; for (unsigned int trk = 0; trk <= unsigned(MaxTrack); trk++) for (unsigned int side = 0; side <= unsigned(MaxSide); side++) { FTrackLength[trk][side] = 6250; FTracksPtr[trk][side][0] = (unsigned char*)new char[FTrackLength[trk][side] + 1024]; // trk img FTracksPtr[trk][side][1] = (unsigned char*)new char[FTrackLength[trk][side] + 1024]; // clk img unsigned int tptr = 0; for (int sec = 0; sec < 16; sec++) { for (r = 0; r < 10; r++) // Первый пробел { FTracksPtr[trk][side][0][tptr] = 0x4E; FTracksPtr[trk][side][1][tptr++] = 0x00; } for (r = 0; r < 12; r++) // Синхропромежуток { FTracksPtr[trk][side][0][tptr] = 0x00; FTracksPtr[trk][side][1][tptr++] = 0x00; } ptrcrc = tptr; for (r = 0; r < 3; r++) // Синхроимпульс { FTracksPtr[trk][side][0][tptr] = 0xA1; FTracksPtr[trk][side][1][tptr++] = 0xFF; } FTracksPtr[trk][side][0][tptr] = 0xFE; // Метка "Адрес" FTracksPtr[trk][side][1][tptr++] = 0x00; FTracksPtr[trk][side][0][tptr] = (unsigned char)trk; // cyl FTracksPtr[trk][side][1][tptr++] = 0x00; FTracksPtr[trk][side][0][tptr] = (unsigned char)0x00; // head (TR always 0) FTracksPtr[trk][side][1][tptr++] = 0x00; FTracksPtr[trk][side][0][tptr] = (unsigned char)(sec + 1); // secN FTracksPtr[trk][side][1][tptr++] = 0x00; FTracksPtr[trk][side][0][tptr] = (unsigned char)0x01; // len=256b FTracksPtr[trk][side][1][tptr++] = 0x00; vgcrc = MakeVGCRC(FTracksPtr[trk][side][0] + ptrcrc, tptr - ptrcrc); FTracksPtr[trk][side][0][tptr] = (unsigned char)(vgcrc >> 8); // VG93 CRC FTracksPtr[trk][side][1][tptr++] = 0x00; FTracksPtr[trk][side][0][tptr] = (unsigned char)(vgcrc & 0xFF); FTracksPtr[trk][side][1][tptr++] = 0x00; for (r = 0; r < 22; r++) // Второй пробел { FTracksPtr[trk][side][0][tptr] = 0x4E; FTracksPtr[trk][side][1][tptr++] = 0x00; } for (r = 0; r < 12; r++) // Синхропромежуток { FTracksPtr[trk][side][0][tptr] = 0x00; FTracksPtr[trk][side][1][tptr++] = 0x00; } ptrcrc = tptr; for (r = 0; r < 3; r++) // Синхроимпульс { FTracksPtr[trk][side][0][tptr] = 0xA1; FTracksPtr[trk][side][1][tptr++] = 0xFF; } FTracksPtr[trk][side][0][tptr] = 0xFB; // Метка "Данные" FTracksPtr[trk][side][1][tptr++] = 0x00; for (r = 0; r < 256; r++) // сектор 256байт { FTracksPtr[trk][side][0][tptr] = 0x00; FTracksPtr[trk][side][1][tptr++] = 0x00; } if ((trk == 0) && (side == 0) && (sec == 8)) // make TR-DOS id { int ssec = tptr - 256; FTracksPtr[trk][side][0][ssec + 0xE1] = 0x00; // first free SECT FTracksPtr[trk][side][0][ssec + 0xE2] = 0x01; // first free TRACK FTracksPtr[trk][side][0][ssec + 0xE3] = 0x16; // 80trk DS FTracksPtr[trk][side][0][ssec + 0xE4] = 0x00; // file count *(unsigned short*)(FTracksPtr[trk][side][0] + ssec + 0xE5) = TotalSecs; // free SECS count FTracksPtr[trk][side][0][ssec + 0xE7] = 0x10; // TR-DOS id FTracksPtr[trk][side][0][ssec + 0xF4] = 0x00; // deleted file count memcpy(FTracksPtr[trk][side][0] + ssec + 0xF5, STR_CREATEDISKNAME" ", 8); // disk name FTracksPtr[trk][side][0][ssec + 0xFD] = 0x00; // zero FTracksPtr[trk][side][0][ssec + 0xFE] = 0x00; // zero FTracksPtr[trk][side][0][ssec + 0xFF] = 0x00; // zero } vgcrc = MakeVGCRC(FTracksPtr[trk][side][0] + ptrcrc, tptr - ptrcrc); FTracksPtr[trk][side][0][tptr] = (unsigned char)(vgcrc >> 8); // VG93 CRC FTracksPtr[trk][side][1][tptr++] = 0x00; FTracksPtr[trk][side][0][tptr] = (unsigned char)(vgcrc & 0xFF); FTracksPtr[trk][side][1][tptr++] = 0x00; for (r = 0; r < 60; r++) // Третий пробел { FTracksPtr[trk][side][0][tptr] = 0x4E; FTracksPtr[trk][side][1][tptr++] = 0x00; } } for (int eoftrk = tptr; eoftrk < 6250; eoftrk++) { FTracksPtr[trk][side][0][tptr] = 0x4E; FTracksPtr[trk][side][1][tptr++] = 0x00; } } } //----------------------------------------------------------------------------- void TDiskImage::readUDI(int hfile, bool ronly) { long fsize = filelength(hfile); if (fsize < 0) { ShowError(ERR_GETLEN); return; } unsigned char *ptr = (unsigned char*)new char[fsize + 1024 * 2048]; if (!ptr) { ShowError(ERR_NOMEM); return; } unsigned long rsize = read(hfile, ptr, fsize + 1024); if (rsize < 16 + 4) { delete ptr; ShowError(ERR_CORRUPT); return; } if (memcmp(ptr, "UDI!", 4) != 0) { delete ptr; ShowError(ERR_FORMAT" UDI!"); return; } UDI_HEADER *udi_hdr = (UDI_HEADER*)(ptr); if ((udi_hdr->Version != 0x00) || (udi_hdr->_zero != 0x00) || (udi_hdr->ExtHdrLength != 0)) { delete ptr; ShowError(ERR_FILEVER" UDI!"); return; } if (rsize != (udi_hdr->UnpackedLength + 4)) { delete ptr; ShowError(ERR_CORRUPT); return; } MaxTrack = udi_hdr->MaxCylinder; MaxSide = udi_hdr->MaxSide; // checking for corrupt... unsigned int udiOFF = 0x10; unsigned int trk, side; for (trk = 0; trk <= unsigned(MaxTrack); trk++) for (side = 0; side <= unsigned(MaxSide); side++) { unsigned char frmt = ptr[udiOFF++]; if (rsize < udiOFF + 4) { delete ptr; ShowError(ERR_CORRUPT); return; } if (frmt) { udiOFF += *((unsigned long*)(ptr + udiOFF)); udiOFF += 4; continue; } unsigned ccctlen = *((unsigned short*)(ptr + udiOFF)); udiOFF += ccctlen; udiOFF += 2; if (rsize < udiOFF + 4) { delete ptr; ShowError(ERR_CORRUPT); return; } udiOFF += ccctlen / 8 + ((ccctlen - (ccctlen / 8) * 8) ? 1 : 0); if (rsize < udiOFF + 4) { delete ptr; ShowError(ERR_CORRUPT); return; } } udiOFF = 0x10; unsigned int trklen; for (trk = 0; trk <= unsigned(MaxTrack); trk++) for (side = 0; side <= unsigned(MaxSide); side++) { if (udiOFF >= rsize) break; if (ptr[udiOFF++] != 0) // non MFM track? { FTrackLength[trk][side] = 6250; // make unformatted track... FTracksPtr[trk][side][0] = (unsigned char*)new char[FTrackLength[trk][side] + 1024]; // trk img FTracksPtr[trk][side][1] = (unsigned char*)new char[FTrackLength[trk][side] + 1024]; // clk img for (unsigned ij = 0; ij < 6250; ij++) { FTracksPtr[trk][side][0][ij] = 0x00; FTracksPtr[trk][side][1][ij] = 0x00; } udiOFF += *((unsigned long*)(ptr + udiOFF)); udiOFF += 4; continue; } trklen = *((unsigned short*)(ptr + udiOFF)); udiOFF += 2; FTrackLength[trk][side] = trklen; // make unformatted track... FTracksPtr[trk][side][0] = (unsigned char*)new char[FTrackLength[trk][side] + 1024]; // trk img FTracksPtr[trk][side][1] = (unsigned char*)new char[FTrackLength[trk][side] + 1024]; // clk img for (unsigned ij = 0; ij < FTrackLength[trk][side]; ij++) { FTracksPtr[trk][side][0][ij] = 0x00; FTracksPtr[trk][side][1][ij] = 0x00; } memcpy(FTracksPtr[trk][side][0], ptr + udiOFF, FTrackLength[trk][side]); udiOFF += trklen; unsigned int MFMinfoLen = trklen / 8 + ((trklen - (trklen / 8) * 8) ? 1 : 0); unsigned char mask; for (unsigned i = 0; i < MFMinfoLen; i++) { mask = 0x01; for (int j = 0; j < 8; j++) { if (ptr[udiOFF] & mask) FTracksPtr[trk][side][1][i * 8 + j] = 0xFF; else FTracksPtr[trk][side][1][i * 8 + j] = 0x00; mask <<= 1; } udiOFF++; } } long CRC = -1l; for (unsigned int i = 0; i < udiOFF; i++) CRC = CalcCRC32(CRC, ptr[i]); if (udiOFF < rsize) if (*((long*)(ptr + udiOFF)) != CRC) ShowError(ERR_FILECRC" UDI!"); delete ptr; ReadOnly = ronly; FType = DIT_UDI; DiskPresent = true; } //----------------------------------------------------------------------------- void TDiskImage::writeTRD(int hfile) { VGFIND_SECTOR vgfs; // prepare nullbuf... unsigned char nullbuf[256]; for (int i = 0; i < 256; i++) nullbuf[i] = '*'; memcpy(nullbuf, errsect, sizeof(errsect)); for (unsigned int trk = 0; trk <= unsigned(MaxTrack); trk++) for (unsigned int side = 0; side <= unsigned(MaxSide); side++) for (unsigned int sec = 0; sec < 16; sec++) { if (FindSector(trk, side, sec + 1, &vgfs)) { write(hfile, vgfs.SectorPointer, 256); if ((!vgfs.CRCOK) || (!vgfs.vgfa.CRCOK)) printf("Warning: sector %d on track %d, side %d with BAD CRC!\n", sec + 1, trk, side); if (vgfs.SectorLength != 256) printf("Warning: sector %d on track %d, side %d is non 256 bytes!\n", sec + 1, trk, side); } else { write(hfile, nullbuf, 256); printf("DANGER! Sector %d on track %d, side %d not found!\n", sec + 1, trk, side); } } } //----------------------------------------------------------------------------- void TDiskImage::readFDI(int hfile, bool readonly) { long fsize = filelength(hfile); if (fsize < 0) { ShowError(ERR_GETLEN); return; } unsigned char *ptr = (unsigned char*)new char[fsize + 1024 * 2048]; if (!ptr) { ShowError(ERR_NOMEM); return; } unsigned long rsize = read(hfile, ptr, fsize); if (rsize < 14) { delete ptr; ShowError(ERR_CORRUPT); return; } if (memcmp(ptr, "FDI", 3) != 0) { delete ptr; ShowError(ERR_FORMAT" FDI!"); return; } // ========================================== // ********** Analyse FDI header ************... // ------------------------------------------ unsigned short *fdihead = (unsigned short*)(ptr + 4); unsigned int fdiCylCount = fdihead[0]; // +4 unsigned int fdiSideCount = fdihead[1]; // +6 // unsigned int fdiOFFtext = fdihead[2]; // +8 unsigned int fdiOFFdata = fdihead[3]; // +A unsigned int fdiSIZEext = fdihead[4]; // +C if ((fdiCylCount > 256) || (fdiCylCount == 0)) { delete ptr; ShowError(ERR_MANYCYLS); return; } if ((fdiSideCount > 256) || (fdiSideCount == 0)) { delete ptr; ShowError(ERR_MANYSIDS); return; } MaxTrack = (unsigned char)(fdiCylCount - 1); MaxSide = (unsigned char)(fdiSideCount - 1); if (rsize < (0x0E + fdiSIZEext + (unsigned(MaxTrack) + 1)*(unsigned(MaxSide) + 1) * 7)) { delete ptr; ShowError(ERR_CORRUPT); return; } struct FDISECINFO { unsigned char ADAM[5]; unsigned int SectorOffset; // относит DataOffset }; struct FDITRACKHDR { unsigned int DataOffset; // относит начала файла unsigned int SectorCount; FDISECINFO SectorsInfo[256]; }; FDITRACKHDR *tracksinfo = new FDITRACKHDR[(unsigned(MaxTrack) + 1)*(unsigned(MaxSide) + 1)]; unsigned int fdiOFF = 0x0E + fdiSIZEext; unsigned int trk, side; // Анализ области заголовков треков... for (trk = 0; trk <= unsigned(MaxTrack); trk++) for (side = 0; side <= unsigned(MaxSide); side++) { if (rsize < fdiOFF) { delete[] tracksinfo; delete ptr; ShowError(ERR_CORRUPT); return; } tracksinfo[trk*(MaxSide + 1) + side].DataOffset = *((unsigned long*)(ptr + fdiOFF)); fdiOFF += 4; if (rsize < fdiOFFdata + tracksinfo[trk*(MaxSide + 1) + side].DataOffset) { delete[] tracksinfo; delete ptr; ShowError(ERR_CORRUPT); return; } fdiOFF += 2; // "Всегда содержит 0 (резерв для модернизации)" tracksinfo[trk*(MaxSide + 1) + side].SectorCount = unsigned(ptr[fdiOFF++]); for (unsigned isec = 0; isec < tracksinfo[trk*(MaxSide + 1) + side].SectorCount; isec++) { memcpy(tracksinfo[trk*(MaxSide + 1) + side].SectorsInfo[isec].ADAM, ptr + fdiOFF, 5); fdiOFF += 5; tracksinfo[trk*(MaxSide + 1) + side].SectorsInfo[isec].SectorOffset = unsigned(*((unsigned short*)(ptr + fdiOFF))); fdiOFF += 2; if (rsize < fdiOFFdata + tracksinfo[trk*(MaxSide + 1) + side].DataOffset + tracksinfo[trk*(MaxSide + 1) + side].SectorsInfo[isec].SectorOffset) { delete[] tracksinfo; delete ptr; ShowError(ERR_CORRUPT); return; } } } // форматирование нового диска и размещение FDI секторов... unsigned int ptrcrc; unsigned int r; unsigned short vgcrc; unsigned int trkdatalen; unsigned SecCount; unsigned SL; for (trk = 0; trk <= unsigned(MaxTrack); trk++) for (side = 0; side <= unsigned(MaxSide); side++) { FTrackLength[trk][side] = 6250; // make unformatted track... FTracksPtr[trk][side][0] = (unsigned char*)new char[FTrackLength[trk][side] + 1024]; // trk img FTracksPtr[trk][side][1] = (unsigned char*)new char[FTrackLength[trk][side] + 1024]; // clk img for (unsigned ij = 0; ij < 6250; ij++) { FTracksPtr[trk][side][0][ij] = 0x00; FTracksPtr[trk][side][1][ij] = 0x00; } SecCount = tracksinfo[trk*(MaxSide + 1) + side].SectorCount; // Вычисляем необходимое число байт под данные: trkdatalen = 0; for (unsigned int ilsec = 0; ilsec < SecCount; ilsec++) { trkdatalen += 2 + 6; // for marks: 0xA1, 0xFE, 6bytes SL = unsigned(tracksinfo[trk*(MaxSide + 1) + side].SectorsInfo[ilsec].ADAM[3]); if (!SL) SL = 128; else SL = 128 << SL; if (tracksinfo[trk*(MaxSide + 1) + side].SectorsInfo[ilsec].ADAM[4] & 0x40) SL = 0; // заголовок без массива данных else trkdatalen += 4; // for data header/crc: 0xA1, 0xFB, ...,2bytes trkdatalen += SL; } if (trkdatalen + SecCount*(3 + 2) > 6250) // 3x4E & 2x00 per sec checking { delete[] tracksinfo; delete ptr; for (int t = 0; t < 256; t++) for (int s = 0; s < 256; s++) { FTrackLength[t][s] = 0; if (FTracksPtr[t][s][0]) delete FTracksPtr[t][s][0]; FTracksPtr[t][s][0] = NULL; if (FTracksPtr[t][s][1]) delete FTracksPtr[t][s][1]; FTracksPtr[t][s][1] = NULL; } ShowError(ERR_IMPOSSIBLE); return; } unsigned int FreeSpace = 6250 - (trkdatalen + SecCount*(3 + 2)); unsigned int SynchroPulseLen = 1; // 1 уже учтен в trkdatalen... unsigned int FirstSpaceLen = 1; unsigned int SecondSpaceLen = 1; unsigned int ThirdSpaceLen = 1; unsigned int SynchroSpaceLen = 1; FreeSpace -= FirstSpaceLen + SecondSpaceLen + ThirdSpaceLen + SynchroSpaceLen; // Распределяем длины пробелов и синхропромежутка: while (FreeSpace > 0) { if (FreeSpace >= (SecCount * 2)) if (SynchroSpaceLen < 12) { SynchroSpaceLen++; FreeSpace -= SecCount * 2; } // Synchro for ADM & DATA if (FreeSpace < SecCount) break; if (FirstSpaceLen < 10) { FirstSpaceLen++; FreeSpace -= SecCount; } if (FreeSpace < SecCount) break; if (SecondSpaceLen < 22) { SecondSpaceLen++; FreeSpace -= SecCount; } if (FreeSpace < SecCount) break; if (ThirdSpaceLen < 60) { ThirdSpaceLen++; FreeSpace -= SecCount; } if (FreeSpace < SecCount) break; if ((SynchroSpaceLen >= 12) && (FirstSpaceLen >= 10) && (SecondSpaceLen >= 22) && (ThirdSpaceLen >= 60)) break; }; // по возможности делаем три синхроимпульса... if (FreeSpace >(SecCount * 2) + 10) { SynchroPulseLen++; FreeSpace -= SecCount; } if (FreeSpace >(SecCount * 2) + 9) SynchroPulseLen++; // Форматируем дорожку... unsigned int tptr = 0; for (unsigned sec = 0; sec < SecCount; sec++) { for (r = 0; r < FirstSpaceLen; r++) // Первый пробел { FTracksPtr[trk][side][0][tptr] = 0x4E; FTracksPtr[trk][side][1][tptr++] = 0x00; } for (r = 0; r < SynchroSpaceLen; r++) // Синхропромежуток { FTracksPtr[trk][side][0][tptr] = 0x00; FTracksPtr[trk][side][1][tptr++] = 0x00; } ptrcrc = tptr; for (r = 0; r < SynchroPulseLen; r++) // Синхроимпульс { FTracksPtr[trk][side][0][tptr] = 0xA1; FTracksPtr[trk][side][1][tptr++] = 0xFF; } FTracksPtr[trk][side][0][tptr] = 0xFE; // Метка "Адрес" FTracksPtr[trk][side][1][tptr++] = 0x00; FTracksPtr[trk][side][0][tptr] = tracksinfo[trk*(MaxSide + 1) + side].SectorsInfo[sec].ADAM[0]; // cyl FTracksPtr[trk][side][1][tptr++] = 0x00; FTracksPtr[trk][side][0][tptr] = tracksinfo[trk*(MaxSide + 1) + side].SectorsInfo[sec].ADAM[1]; // head FTracksPtr[trk][side][1][tptr++] = 0x00; FTracksPtr[trk][side][0][tptr] = tracksinfo[trk*(MaxSide + 1) + side].SectorsInfo[sec].ADAM[2]; // secN FTracksPtr[trk][side][1][tptr++] = 0x00; FTracksPtr[trk][side][0][tptr] = tracksinfo[trk*(MaxSide + 1) + side].SectorsInfo[sec].ADAM[3]; // len code FTracksPtr[trk][side][1][tptr++] = 0x00; vgcrc = MakeVGCRC(FTracksPtr[trk][side][0] + ptrcrc, tptr - ptrcrc); FTracksPtr[trk][side][0][tptr] = (unsigned char)(vgcrc >> 8); // VG93 CRC FTracksPtr[trk][side][1][tptr++] = 0x00; FTracksPtr[trk][side][0][tptr] = (unsigned char)(vgcrc & 0xFF); FTracksPtr[trk][side][1][tptr++] = 0x00; for (r = 0; r < SecondSpaceLen; r++) // Второй пробел { FTracksPtr[trk][side][0][tptr] = 0x4E; FTracksPtr[trk][side][1][tptr++] = 0x00; } for (r = 0; r < SynchroSpaceLen; r++) // Синхропромежуток { FTracksPtr[trk][side][0][tptr] = 0x00; FTracksPtr[trk][side][1][tptr++] = 0x00; } unsigned char fdiSectorFlags = tracksinfo[trk*(MaxSide + 1) + side].SectorsInfo[sec].ADAM[4]; // !!!!!!!!! // !WARNING! this feature of FDI format is NOT FULL DOCUMENTED!!! // !!!!!!!!! // // Flags::bit6 - Возможно, 1 в данном разряде // будет обозначать адресный маркер без области данных. // if (!(fdiSectorFlags & 0x40)) // oh-oh, data area not present... ;-) { ptrcrc = tptr; for (r = 0; r < SynchroPulseLen; r++) // Синхроимпульс { FTracksPtr[trk][side][0][tptr] = 0xA1; FTracksPtr[trk][side][1][tptr++] = 0xFF; } if (fdiSectorFlags & 0x80) FTracksPtr[trk][side][0][tptr] = 0xF8; // Метка "Удаленные данные" else FTracksPtr[trk][side][0][tptr] = 0xFB; // Метка "Данные" FTracksPtr[trk][side][1][tptr++] = 0x00; SL = unsigned(tracksinfo[trk*(MaxSide + 1) + side].SectorsInfo[sec].ADAM[3]); if (!SL) SL = 128; else SL = 128 << SL; unsigned int secDATAOFF = fdiOFFdata + tracksinfo[trk*(MaxSide + 1) + side].DataOffset + tracksinfo[trk*(MaxSide + 1) + side].SectorsInfo[sec].SectorOffset; for (r = 0; r < SL; r++) // сектор SL байт { FTracksPtr[trk][side][0][tptr] = ptr[secDATAOFF + r]; FTracksPtr[trk][side][1][tptr++] = 0x00; } vgcrc = MakeVGCRC(FTracksPtr[trk][side][0] + ptrcrc, tptr - ptrcrc); if (fdiSectorFlags & 0x3F) // CRC correct? { FTracksPtr[trk][side][0][tptr] = (unsigned char)(vgcrc >> 8); // VG93 CRC FTracksPtr[trk][side][1][tptr++] = 0x00; FTracksPtr[trk][side][0][tptr] = (unsigned char)(vgcrc & 0xFF); FTracksPtr[trk][side][1][tptr++] = 0x00; } else // oh-oh, high technology... CRC bad... ;-) { FTracksPtr[trk][side][0][tptr] = (unsigned char)(vgcrc >> 8) ^ 0xFF; // emulation bad CRC... ;) FTracksPtr[trk][side][1][tptr++] = 0x00; FTracksPtr[trk][side][0][tptr] = (unsigned char)(vgcrc & 0xFF) ^ 0xFF; // --//-- ;) FTracksPtr[trk][side][1][tptr++] = 0x00; } } for (r = 0; r < ThirdSpaceLen; r++) // Третий пробел { FTracksPtr[trk][side][0][tptr] = 0x4E; FTracksPtr[trk][side][1][tptr++] = 0x00; } } for (int eoftrk = tptr; eoftrk < 6250; eoftrk++) { FTracksPtr[trk][side][0][tptr] = 0x4E; FTracksPtr[trk][side][1][tptr++] = 0x00; } } delete[] tracksinfo; delete ptr; ReadOnly = readonly; FType = DIT_FDI; DiskPresent = true; } //----------------------------------------------------------------------------- void TDiskImage::readFDD(int hfile, bool readonly) { long fsize = filelength(hfile); if (fsize < 0) { ShowError(ERR_GETLEN); return; } unsigned char *ptr = (unsigned char*)new char[fsize + 1024 * 32]; if (!ptr) { ShowError(ERR_NOMEM); return; } unsigned long rsize = read(hfile, ptr, fsize); if (rsize < sizeof(FDD_MAIN_HEADER)) { delete ptr; ShowError(ERR_CORRUPT); return; } FDD_MAIN_HEADER *fdd_hdr = (FDD_MAIN_HEADER*)ptr; int MaxC = fdd_hdr->MaxTracks; int MaxH = fdd_hdr->MaxHeads; if (MaxH > 2) { delete ptr; ShowError(ERR_MANYSIDS); return; } MaxH = (MaxH - 1) & 0xFF; MaxC = (MaxC - 1) & 0xFF; MaxTrack = MaxC; MaxSide = MaxH; // форматирование нового диска и размещение FDD секторов... unsigned int ptrcrc; unsigned int r; unsigned short vgcrc; unsigned int trkdatalen; unsigned SecCount; unsigned SL; FDD_TRACK_HEADER *trackinfo; unsigned int trk, side; for (trk = 0; trk <= unsigned(MaxTrack); trk++) for (side = 0; side <= unsigned(MaxSide); side++) { FTrackLength[trk][side] = 6250; // make unformatted track... FTracksPtr[trk][side][0] = (unsigned char*)new char[FTrackLength[trk][side] + 1024]; // trk img FTracksPtr[trk][side][1] = (unsigned char*)new char[FTrackLength[trk][side] + 1024]; // clk img for (unsigned ij = 0; ij < 6250; ij++) { FTracksPtr[trk][side][0][ij] = 0x00; FTracksPtr[trk][side][1][ij] = 0x00; } if ((fdd_hdr->DataOffset[trk*(MaxSide + 1) + side] + 2) > int(rsize)) { delete ptr; for (int t = 0; t < 256; t++) for (int s = 0; s < 256; s++) { FTrackLength[t][s] = 0; if (FTracksPtr[t][s][0]) delete FTracksPtr[t][s][0]; FTracksPtr[t][s][0] = NULL; if (FTracksPtr[t][s][1]) delete FTracksPtr[t][s][1]; FTracksPtr[t][s][1] = NULL; } ShowError(ERR_CORRUPT); return; } trackinfo = (FDD_TRACK_HEADER *)(ptr + fdd_hdr->DataOffset[trk*(MaxSide + 1) + side]); SecCount = trackinfo->SectNum; if ((2 + SecCount * 8 + fdd_hdr->DataOffset[trk*(MaxSide + 1) + side]) > rsize) { delete ptr; for (int t = 0; t < 256; t++) for (int s = 0; s < 256; s++) { FTrackLength[t][s] = 0; if (FTracksPtr[t][s][0]) delete FTracksPtr[t][s][0]; FTracksPtr[t][s][0] = NULL; if (FTracksPtr[t][s][1]) delete FTracksPtr[t][s][1]; FTracksPtr[t][s][1] = NULL; } ShowError(ERR_CORRUPT); return; } else if (trackinfo->sect[SecCount - 1].SectPos > int(rsize)) { delete ptr; for (int t = 0; t < 256; t++) for (int s = 0; s < 256; s++) { FTrackLength[t][s] = 0; if (FTracksPtr[t][s][0]) delete FTracksPtr[t][s][0]; FTracksPtr[t][s][0] = NULL; if (FTracksPtr[t][s][1]) delete FTracksPtr[t][s][1]; FTracksPtr[t][s][1] = NULL; } ShowError(ERR_CORRUPT); return; } // Вычисляем необходимое число байт под данные: trkdatalen = 0; for (unsigned int ilsec = 0; ilsec < SecCount; ilsec++) { trkdatalen += 2 + 6; // for marks: 0xA1, 0xFE, 6bytes SL = unsigned(trackinfo->sect[ilsec].size); if (!SL) SL = 128; else SL = 128 << SL; trkdatalen += 4; // for data header/crc: 0xA1, 0xFB, ...,2bytes trkdatalen += SL; } if (trkdatalen + SecCount*(3 + 2) > 6250) // 3x4E & 2x00 per sec checking { delete ptr; for (int t = 0; t < 256; t++) for (int s = 0; s < 256; s++) { FTrackLength[t][s] = 0; if (FTracksPtr[t][s][0]) delete FTracksPtr[t][s][0]; FTracksPtr[t][s][0] = NULL; if (FTracksPtr[t][s][1]) delete FTracksPtr[t][s][1]; FTracksPtr[t][s][1] = NULL; } ShowError(ERR_IMPOSSIBLE); return; } unsigned int FreeSpace = 6250 - (trkdatalen + SecCount*(3 + 2)); unsigned int SynchroPulseLen = 1; // 1 уже учтен в trkdatalen... unsigned int FirstSpaceLen = 1; unsigned int SecondSpaceLen = 1; unsigned int ThirdSpaceLen = 1; unsigned int SynchroSpaceLen = 1; FreeSpace -= FirstSpaceLen + SecondSpaceLen + ThirdSpaceLen + SynchroSpaceLen; // Распределяем длины пробелов и синхропромежутка: while (FreeSpace > 0) { if (FreeSpace >= (SecCount * 2)) if (SynchroSpaceLen < 12) { SynchroSpaceLen++; FreeSpace -= SecCount * 2; } // Synchro for ADM & DATA if (FreeSpace < SecCount) break; if (FirstSpaceLen < 10) { FirstSpaceLen++; FreeSpace -= SecCount; } if (FreeSpace < SecCount) break; if (SecondSpaceLen < 22) { SecondSpaceLen++; FreeSpace -= SecCount; } if (FreeSpace < SecCount) break; if (ThirdSpaceLen < 60) { ThirdSpaceLen++; FreeSpace -= SecCount; } if (FreeSpace < SecCount) break; if ((SynchroSpaceLen >= 12) && (FirstSpaceLen >= 10) && (SecondSpaceLen >= 22) && (ThirdSpaceLen >= 60)) break; }; // по возможности делаем три синхроимпульса... if (FreeSpace >(SecCount * 2) + 10) { SynchroPulseLen++; FreeSpace -= SecCount; } if (FreeSpace >(SecCount * 2) + 9) SynchroPulseLen++; // Форматируем дорожку... unsigned int tptr = 0; for (unsigned sec = 0; sec < SecCount; sec++) { for (r = 0; r < FirstSpaceLen; r++) // Первый пробел { FTracksPtr[trk][side][0][tptr] = 0x4E; FTracksPtr[trk][side][1][tptr++] = 0x00; } for (r = 0; r < SynchroSpaceLen; r++) // Синхропромежуток { FTracksPtr[trk][side][0][tptr] = 0x00; FTracksPtr[trk][side][1][tptr++] = 0x00; } ptrcrc = tptr; for (r = 0; r < SynchroPulseLen; r++) // Синхроимпульс { FTracksPtr[trk][side][0][tptr] = 0xA1; FTracksPtr[trk][side][1][tptr++] = 0xFF; } FTracksPtr[trk][side][0][tptr] = 0xFE; // Метка "Адрес" FTracksPtr[trk][side][1][tptr++] = 0x00; FTracksPtr[trk][side][0][tptr] = trackinfo->sect[sec].trk; // cyl FTracksPtr[trk][side][1][tptr++] = 0x00; FTracksPtr[trk][side][0][tptr] = trackinfo->sect[sec].side; // head FTracksPtr[trk][side][1][tptr++] = 0x00; FTracksPtr[trk][side][0][tptr] = trackinfo->sect[sec].sect; // secN FTracksPtr[trk][side][1][tptr++] = 0x00; FTracksPtr[trk][side][0][tptr] = trackinfo->sect[sec].size; // len code FTracksPtr[trk][side][1][tptr++] = 0x00; vgcrc = MakeVGCRC(FTracksPtr[trk][side][0] + ptrcrc, tptr - ptrcrc); FTracksPtr[trk][side][0][tptr] = (unsigned char)(vgcrc >> 8); // VG93 CRC FTracksPtr[trk][side][1][tptr++] = 0x00; FTracksPtr[trk][side][0][tptr] = (unsigned char)(vgcrc & 0xFF); FTracksPtr[trk][side][1][tptr++] = 0x00; for (r = 0; r < SecondSpaceLen; r++) // Второй пробел { FTracksPtr[trk][side][0][tptr] = 0x4E; FTracksPtr[trk][side][1][tptr++] = 0x00; } for (r = 0; r < SynchroSpaceLen; r++) // Синхропромежуток { FTracksPtr[trk][side][0][tptr] = 0x00; FTracksPtr[trk][side][1][tptr++] = 0x00; } // DATA AM ptrcrc = tptr; for (r = 0; r < SynchroPulseLen; r++) // Синхроимпульс { FTracksPtr[trk][side][0][tptr] = 0xA1; FTracksPtr[trk][side][1][tptr++] = 0xFF; } FTracksPtr[trk][side][0][tptr] = 0xFB; // Метка "Данные" FTracksPtr[trk][side][1][tptr++] = 0x00; SL = unsigned(trackinfo->sect[sec].size); if (!SL) SL = 128; else SL = 128 << SL; unsigned int secDATAOFF = trackinfo->sect[sec].SectPos; for (r = 0; r < SL; r++) // сектор SL байт { FTracksPtr[trk][side][0][tptr] = ptr[secDATAOFF + r]; FTracksPtr[trk][side][1][tptr++] = 0x00; } vgcrc = MakeVGCRC(FTracksPtr[trk][side][0] + ptrcrc, tptr - ptrcrc); FTracksPtr[trk][side][0][tptr] = (unsigned char)(vgcrc >> 8); // VG93 CRC FTracksPtr[trk][side][1][tptr++] = 0x00; FTracksPtr[trk][side][0][tptr] = (unsigned char)(vgcrc & 0xFF); FTracksPtr[trk][side][1][tptr++] = 0x00; for (r = 0; r < ThirdSpaceLen; r++) // Третий пробел { FTracksPtr[trk][side][0][tptr] = 0x4E; FTracksPtr[trk][side][1][tptr++] = 0x00; } } for (int eoftrk = tptr; eoftrk < 6250; eoftrk++) { FTracksPtr[trk][side][0][tptr] = 0x4E; FTracksPtr[trk][side][1][tptr++] = 0x00; } } delete ptr; ReadOnly = readonly; FType = DIT_FDD; DiskPresent = true; } //----------------------------------------------------------------------------- void TDiskImage::readSCL(int hfile, bool readonly) { long fsize = filelength(hfile); if (fsize < 0) { ShowError(ERR_GETLEN); return; } unsigned char *ptr = (unsigned char*)new char[fsize + 1024 * 2048]; if (!ptr) { ShowError(ERR_NOMEM); return; } unsigned long rsize = read(hfile, ptr, fsize); if (!rsize) { delete ptr; ShowError(ERR_CORRUPT); return; } if (rsize < 9 + 4) // header { delete ptr; ShowError(ERR_CORRUPT); return; } if (memcmp(ptr, "SINCLAIR", 8) != 0) { delete ptr; ShowError(ERR_FORMAT" SCL!"); return; } unsigned int FileCount = ptr[8]; if (rsize < 9 + 4 + FileCount * 14) { delete ptr; ShowError(ERR_CORRUPT); return; } TRDOS_DIR_ELEMENT *fileinfo[256]; unsigned short FilesTotalSecs = 0; // checking for corrupt + SCL-CRC + FileDIRS parse unsigned long SCLCRC = 0; unsigned sclOFF = 0; unsigned int i, j; for (i = 0; i < 9; i++) SCLCRC += unsigned(ptr[sclOFF++]); for (i = 0; i < FileCount; i++) { fileinfo[i] = (TRDOS_DIR_ELEMENT*)(ptr + sclOFF); for (j = 0; j < 14; j++) SCLCRC += unsigned(ptr[sclOFF++]); } for (i = 0; i < FileCount; i++) { unsigned SL = unsigned(fileinfo[i]->SecLen) * 256; FilesTotalSecs += fileinfo[i]->SecLen; if (rsize < sclOFF + 4 + SL) { delete ptr; ShowError(ERR_CORRUPT); return; } for (j = 0; j < SL; j++) SCLCRC += unsigned(ptr[sclOFF++]); } if (*((unsigned long*)(ptr + sclOFF)) != SCLCRC) ShowError(ERR_FILECRC" SCL!"); if (FilesTotalSecs < 2544) FilesTotalSecs = 2544; else { int cyls = ((16 + FilesTotalSecs) / (16 * 2)) + (((16 + FilesTotalSecs) % (16 * 2)) ? 1 : 0); FilesTotalSecs = (cyls * 16 * 2) - 16; } formatTRDOS((FilesTotalSecs + 16) / (16 * 2), 2); ReadOnly = true; FType = DIT_SCL; DiskPresent = true; sclOFF = 9 + 14 * FileCount; bool BOOTADD = true; unsigned char _FileCount = 0; unsigned char _DelFileCount = 0; for (i = 0; i < FileCount; i++) { if (fileinfo[i]->FileName[0] == 0x01) _DelFileCount++; _FileCount++; if (!strncasecmp(fileinfo[i]->FileName, "BOOT B", 9)) { BOOTADD = false; } } unsigned char SEC = 0, TRK = 1; unsigned short FreeSEC = 2544; unsigned int cnt = 0; unsigned int dirsec; TRDOS_DIR_ELEMENT trdosde; VGFIND_SECTOR vgfs; if (BOOTADD && (unsigned(_FileCount) + unsigned(_DelFileCount) < 127)) { dirsec = ((cnt * 16) / 256) + 1; memcpy(&trdosde, &sbootdir, sizeof(sbootdir)); trdosde.FirstSec = SEC; trdosde.FirstTrk = TRK; if (FindSector(0, 0, dirsec, &vgfs)) // DIR ELEMENT write { memcpy(vgfs.SectorPointer + ((cnt * 16) % 256), &trdosde, sizeof(trdosde)); ApplySectorCRC(vgfs); } _FileCount++; cnt++; int _bOFF = 0; for (j = 0; j < unsigned(trdosde.SecLen); j++) { if (FindSector(TRK / 2, TRK % 2, SEC + 1, &vgfs)) // SECTOR write { memcpy(vgfs.SectorPointer, sbootimage + _bOFF, 256); ApplySectorCRC(vgfs); } _bOFF += 256; SEC++; FreeSEC--; if (SEC > 15) { SEC = 0; TRK++; } } } for (i = 0; i < FileCount; i++) { if (TRK >= (MaxTrack + 1)*(MaxSide + 1)) break; // disk full ? memcpy(&trdosde, fileinfo[i], 14); trdosde.FirstSec = SEC; trdosde.FirstTrk = TRK; unsigned int dirsec = ((cnt * 16) / 256) + 1; if (FindSector(0, 0, dirsec, &vgfs)) // DIR ELEMENT write { memcpy(vgfs.SectorPointer + ((cnt * 16) % 256), &trdosde, 16); ApplySectorCRC(vgfs); } cnt++; for (j = 0; j < unsigned(trdosde.SecLen); j++) { if (FindSector(TRK / 2, TRK % 2, SEC + 1, &vgfs)) // SECTOR write { memcpy(vgfs.SectorPointer, ptr + sclOFF, 256); ApplySectorCRC(vgfs); } sclOFF += 256; SEC++; FreeSEC--; if (SEC > 15) { SEC = 0; TRK++; } if (TRK >= (MaxTrack + 1)*(MaxSide + 1)) break; // disk full ? } } if (FindSector(0, 0, 9, &vgfs)) // update disk info { vgfs.SectorPointer[0xE1] = SEC; vgfs.SectorPointer[0xE2] = TRK; vgfs.SectorPointer[0xE4] = _FileCount; vgfs.SectorPointer[0xF4] = _DelFileCount; *((unsigned short*)(vgfs.SectorPointer + 0xE5)) = FreeSEC; ApplySectorCRC(vgfs); } delete ptr; ReadOnly = readonly; } //----------------------------------------------------------------------------- void TDiskImage::readHOB(int hfile) { long fsize = filelength(hfile); if (fsize < 0) { ShowError(ERR_GETLEN); return; } unsigned char *ptr = (unsigned char*)new char[fsize + 1024 * 2048]; if (!ptr) { ShowError(ERR_NOMEM); return; } unsigned long rsize = read(hfile, ptr, fsize); if (!rsize) { delete ptr; ShowError(ERR_CORRUPT); return; } if (rsize < 17) // header { delete ptr; ShowError(ERR_CORRUPT); return; } TRDOS_DIR_ELEMENT dired; memcpy(&dired, ptr, 14); unsigned short hobRealCRC = *((unsigned short*)(ptr + 0x0F)); unsigned int DataLength = *((unsigned short*)(ptr + 0x0D)); if (rsize < 17 + (DataLength & 0xFF00)) { delete ptr; ShowError(ERR_CORRUPT); return; } unsigned int i; unsigned short CRC = 0; for (i = 0; i < 15; i++) CRC = CRC + ptr[i]; CRC *= 257; CRC += 105; // сумма чисел от 0 до 14 if (CRC != hobRealCRC) ShowError(ERR_FILECRC" HOBETA!"); ReadOnly = true; if (!DiskPresent) { formatTRDOS(80, 2); FType = DIT_HOB; DiskPresent = true; } // --- read file... dired.SecLen = ptr[0x0E]; // число секторов файла VGFIND_SECTOR vgfs9; if (!FindSector(0, 0, 9, &vgfs9)) { delete ptr; return; } dired.FirstSec = vgfs9.SectorPointer[0xE1]; dired.FirstTrk = vgfs9.SectorPointer[0xE2]; VGFIND_SECTOR vgfs; unsigned char SEC = dired.FirstSec, TRK = dired.FirstTrk; unsigned short FreeSEC = *((unsigned short*)(vgfs9.SectorPointer + 0xE5)); unsigned char FileCount = vgfs9.SectorPointer[0xE4]; unsigned char DelFileCount = vgfs9.SectorPointer[0xF4]; if (TRK >= 160) // disk full ? { delete ptr; return; } for (unsigned int j = 0; j < unsigned(dired.SecLen); j++) { if (FindSector(TRK / 2, TRK % 2, SEC + 1, &vgfs)) { memcpy(vgfs.SectorPointer, ptr + 17 + j * 256, 256); ApplySectorCRC(vgfs); } SEC++; FreeSEC--; if (SEC > 15) { SEC = 0; TRK++; } if (TRK >= 160) break; // disk full? } if (FindSector(0, 0, ((FileCount * 16) / 256) + 1, &vgfs)) { memcpy(vgfs.SectorPointer + ((FileCount * 16) % 256), &dired, 16); ApplySectorCRC(vgfs); } if (dired.FileName[0] == 0x01) DelFileCount++; FileCount++; vgfs9.SectorPointer[0xE1] = SEC; vgfs9.SectorPointer[0xE2] = TRK; *((unsigned short*)(vgfs9.SectorPointer + 0xE5)) = FreeSEC; vgfs9.SectorPointer[0xE4] = FileCount; vgfs9.SectorPointer[0xF4] = DelFileCount; ApplySectorCRC(vgfs9); } //----------------------------------------------------------------------------- bool unpack_td0(unsigned char *data, long &size); unsigned short TD0CRC(unsigned char *buf, unsigned int len); #define WORD2(a,b) ((a)+(b)*0x100) void TDiskImage::readTD0(int hfile, bool readonly) { long fsize = filelength(hfile); if (fsize < 0) { ShowError(ERR_GETLEN); return; } unsigned char *ptr = (unsigned char*)new char[fsize + 256 * 20000]; if (!ptr) { ShowError(ERR_NOMEM); return; } long rsize = read(hfile, ptr, fsize); TD0_MAIN_HEADER *td0hdr = (TD0_MAIN_HEADER*)ptr; TD0_INFO_DATA *td0inf = (TD0_INFO_DATA*)(ptr + 12); if (!rsize) { delete ptr; ShowError(ERR_CORRUPT); return; } if (rsize < 12) // header { delete ptr; ShowError(ERR_CORRUPT); return; } if ((*(short*)ptr != WORD2('T', 'D')) && (*(short*)ptr != WORD2('t', 'd')))// non TD0 { delete ptr; ShowError(ERR_FORMAT" TD0!"); return; } if (TD0CRC(ptr, 10) != td0hdr->CRC) // CRC bad... { delete ptr; ShowError(ERR_FILECRC" TD0!"); return; } if ((td0hdr->Ver > 21) || (td0hdr->Ver < 10)) // 1.0 <= version <= 2.1... { delete ptr; ShowError(ERR_FILEVER" TD0!"); return; } if (td0hdr->DataDOS != 0) // if DOS allocated sectors only... { delete ptr; ShowError(ERR_TD0DOSALLOC); return; } if (!unpack_td0(ptr, rsize)) { delete ptr; ShowError(ERR_FORMAT" TD0!"); return; } // loading unpacked TD0... int tdOFF = 12; if (ptr[7] & 0x80) tdOFF += sizeof(TD0_INFO_DATA) + td0inf->strLen; TD0_TRACK_HEADER *tdtrk; TD0_SECT_HEADER *tdsect; MaxTrack = 0; MaxSide = 0; for (; tdOFF < rsize;) { tdtrk = (TD0_TRACK_HEADER*)(ptr + tdOFF); tdOFF += sizeof(TD0_TRACK_HEADER); if (tdOFF >= rsize) break; if (tdtrk->SectorCount == 0xFF) break; // EOF marker unsigned trk = tdtrk->Track; unsigned side = tdtrk->Side; FTrackLength[trk][side] = 6250; // make unformatted track... FTracksPtr[trk][side][0] = (unsigned char*)new char[FTrackLength[trk][side] + 1024]; // trk img FTracksPtr[trk][side][1] = (unsigned char*)new char[FTrackLength[trk][side] + 1024]; // clk img for (unsigned ij = 0; ij < 6250; ij++) { FTracksPtr[trk][side][0][ij] = 0x00; FTracksPtr[trk][side][1][ij] = 0x00; } unsigned SecCount = tdtrk->SectorCount; unsigned int tmpOFF = tdOFF; // Вычисляем необходимое число байт под данные: unsigned int trkdatalen = 0; unsigned int SL; for (unsigned int ilsec = 0; ilsec < SecCount; ilsec++) { tdsect = (TD0_SECT_HEADER*)(ptr + tmpOFF); tmpOFF += sizeof(TD0_SECT_HEADER) + tdsect->DataLength; trkdatalen += 2 + 6; // for marks: 0xA1, 0xFE, 6bytes trkdatalen += 4; // for data header/crc: 0xA1, 0xFB, ...,2bytes // SL = unsigned(tdsect->ADRM[3]); // if(!SL) SL = 128; // else SL = 128 << SL; SL = tdsect->DataLength - 1; trkdatalen += SL; } // проверка на возможность формата... if (trkdatalen + SecCount*(3 + 2) > 6250) // 3x4E & 2x00 per sec checking { delete ptr; for (int t = 0; t < 256; t++) for (int s = 0; s < 256; s++) { FTrackLength[t][s] = 0; if (FTracksPtr[t][s][0]) delete FTracksPtr[t][s][0]; FTracksPtr[t][s][0] = NULL; if (FTracksPtr[t][s][1]) delete FTracksPtr[t][s][1]; FTracksPtr[t][s][1] = NULL; } ShowError(ERR_IMPOSSIBLE); return; } unsigned int FreeSpace = 6250 - (trkdatalen + SecCount*(3 + 2)); unsigned int SynchroPulseLen = 1; // 1 уже учтен в trkdatalen... unsigned int FirstSpaceLen = 1; unsigned int SecondSpaceLen = 1; unsigned int ThirdSpaceLen = 1; unsigned int SynchroSpaceLen = 1; FreeSpace -= FirstSpaceLen + SecondSpaceLen + ThirdSpaceLen + SynchroSpaceLen; // Распределяем длины пробелов и синхропромежутка: while (FreeSpace > 0) { if (FreeSpace >= (SecCount * 2)) if (SynchroSpaceLen < 12) { SynchroSpaceLen++; FreeSpace -= SecCount * 2; } // Synchro for ADM & DATA if (FreeSpace < SecCount) break; if (FirstSpaceLen < 10) { FirstSpaceLen++; FreeSpace -= SecCount; } if (FreeSpace < SecCount) break; if (SecondSpaceLen < 22) { SecondSpaceLen++; FreeSpace -= SecCount; } if (FreeSpace < SecCount) break; if (ThirdSpaceLen < 60) { ThirdSpaceLen++; FreeSpace -= SecCount; } if (FreeSpace < SecCount) break; if ((SynchroSpaceLen >= 12) && (FirstSpaceLen >= 10) && (SecondSpaceLen >= 22) && (ThirdSpaceLen >= 60)) break; }; // по возможности делаем три синхроимпульса... if (FreeSpace >(SecCount * 2) + 10) { SynchroPulseLen++; FreeSpace -= SecCount; } if (FreeSpace >(SecCount * 2) + 9) SynchroPulseLen++; // Форматируем дорожку... unsigned int tptr = 0; unsigned int ptrcrc; unsigned int r; unsigned short vgcrc; for (unsigned sec = 0; sec < SecCount; sec++) { tdsect = (TD0_SECT_HEADER*)(ptr + tdOFF); tdOFF += sizeof(TD0_SECT_HEADER) + 1; for (r = 0; r < FirstSpaceLen; r++) // Первый пробел { FTracksPtr[trk][side][0][tptr] = 0x4E; FTracksPtr[trk][side][1][tptr++] = 0x00; } for (r = 0; r < SynchroSpaceLen; r++) // Синхропромежуток { FTracksPtr[trk][side][0][tptr] = 0x00; FTracksPtr[trk][side][1][tptr++] = 0x00; } ptrcrc = tptr; for (r = 0; r < SynchroPulseLen; r++) // Синхроимпульс { FTracksPtr[trk][side][0][tptr] = 0xA1; FTracksPtr[trk][side][1][tptr++] = 0xFF; } FTracksPtr[trk][side][0][tptr] = 0xFE; // Метка "Адрес" FTracksPtr[trk][side][1][tptr++] = 0x00; FTracksPtr[trk][side][0][tptr] = tdsect->ADRM[0]; // cyl FTracksPtr[trk][side][1][tptr++] = 0x00; FTracksPtr[trk][side][0][tptr] = tdsect->ADRM[1]; // head FTracksPtr[trk][side][1][tptr++] = 0x00; FTracksPtr[trk][side][0][tptr] = tdsect->ADRM[2]; // secN FTracksPtr[trk][side][1][tptr++] = 0x00; FTracksPtr[trk][side][0][tptr] = tdsect->ADRM[3]; // len code FTracksPtr[trk][side][1][tptr++] = 0x00; vgcrc = MakeVGCRC(FTracksPtr[trk][side][0] + ptrcrc, tptr - ptrcrc); FTracksPtr[trk][side][0][tptr] = (unsigned char)(vgcrc >> 8); // VG93 CRC FTracksPtr[trk][side][1][tptr++] = 0x00; FTracksPtr[trk][side][0][tptr] = (unsigned char)(vgcrc & 0xFF); FTracksPtr[trk][side][1][tptr++] = 0x00; for (r = 0; r < SecondSpaceLen; r++) // Второй пробел { FTracksPtr[trk][side][0][tptr] = 0x4E; FTracksPtr[trk][side][1][tptr++] = 0x00; } for (r = 0; r < SynchroSpaceLen; r++) // Синхропромежуток { FTracksPtr[trk][side][0][tptr] = 0x00; FTracksPtr[trk][side][1][tptr++] = 0x00; } if (tdsect->DataLength - 1) // oh-oh, data area not present... ;-) { ptrcrc = tptr; for (r = 0; r < SynchroPulseLen; r++) // Синхроимпульс { FTracksPtr[trk][side][0][tptr] = 0xA1; FTracksPtr[trk][side][1][tptr++] = 0xFF; } FTracksPtr[trk][side][0][tptr] = 0xFB; // Метка "Данные" FTracksPtr[trk][side][1][tptr++] = 0x00; // SL = unsigned(tdsect->ADRM[3]); // if(!SL) SL = 128; // else SL = 128 << SL; SL = tdsect->DataLength - 1; for (r = 0; r < SL; r++) // сектор SL байт { FTracksPtr[trk][side][0][tptr] = ptr[tdOFF + r]; FTracksPtr[trk][side][1][tptr++] = 0x00; } tdOFF += SL; vgcrc = MakeVGCRC(FTracksPtr[trk][side][0] + ptrcrc, tptr - ptrcrc); FTracksPtr[trk][side][0][tptr] = (unsigned char)(vgcrc >> 8); // VG93 CRC FTracksPtr[trk][side][1][tptr++] = 0x00; FTracksPtr[trk][side][0][tptr] = (unsigned char)(vgcrc & 0xFF); FTracksPtr[trk][side][1][tptr++] = 0x00; } for (r = 0; r < ThirdSpaceLen; r++) // Третий пробел { FTracksPtr[trk][side][0][tptr] = 0x4E; FTracksPtr[trk][side][1][tptr++] = 0x00; } } for (int eoftrk = tptr; eoftrk < 6250; eoftrk++) { FTracksPtr[trk][side][0][tptr] = 0x4E; FTracksPtr[trk][side][1][tptr++] = 0x00; } if (unsigned(MaxTrack) < trk) MaxTrack = trk; if (unsigned(MaxSide) < side) MaxSide = side; } delete ptr; ReadOnly = readonly; FType = DIT_TD0; DiskPresent = true; } //----------------------------------------------------------------------------- void TDiskImage::ShowError(const char *str) { printf("DiskImage Error: %s\n", str); } //----------------------------------------------------------------------------- // convert packed td0 to unpacked unsigned short TD0CRC(unsigned char *buf, unsigned int len); unsigned unpack_lzh(unsigned char *src, unsigned size, unsigned char *buf); unsigned char *td0_dst, *td0_src; void td0_move(unsigned size) { memcpy(td0_dst, td0_src, size); td0_dst += size; td0_src += size; } //---------------------------------------------------------------------------- bool unpack_td0(unsigned char *data, long &size) { if (size < 12) return false; if ((*(short*)data != WORD2('T', 'D')) && (*(short*)data != WORD2('t', 'd'))) return false; // non TD0 if (TD0CRC(data, 10) != *((unsigned short*)(data + 0x0A))) return false; // CRC bad... if (data[4] > 21) return false; // version > 2.1... unsigned char *snbuf = (unsigned char*)new char[size * 2 + 1500000]; // if compressed then UUUUFF ;-/ if (!snbuf) return false; memcpy(snbuf, data, size); if (*(short*)snbuf == WORD2('t', 'd')) // packed disk { if (snbuf[4] < 20) // unsupported Old Advanced compression { delete snbuf; return false; } unpack_lzh((unsigned char*)data + 12, size - 12, (unsigned char*)snbuf + 12), *(short*)snbuf = WORD2('T', 'D'); } td0_src = snbuf, td0_dst = data; td0_move(12); if (snbuf[7] & 0x80) // additional info... { unsigned short *cs = (unsigned short*)(snbuf + 12 + 2); if (TD0CRC(snbuf + 12 + 2, 8 + *cs) != cs[-1]) { delete snbuf; return false; } td0_move(10); td0_move(*((unsigned short*)(snbuf + 12 + 2))); } for (;;) { unsigned char s = *td0_src; td0_move(4); if (s == 0xFF) break; for (; s; s--) { // unsigned char *sec = td0_src; unsigned size = 128; if (td0_src[3]) size <<= td0_src[3]; td0_move(6); *(unsigned short*)td0_dst = size + 1; td0_dst += 2; *td0_dst++ = 0; unsigned char *dst = td0_dst; unsigned src_size = *(unsigned short*)td0_src; td0_src += 2; unsigned char *end_packed_data = td0_src + src_size; memset(td0_dst, 0, size); switch (*td0_src++) { case 0: memcpy(dst, td0_src, src_size - 1); break; case 1: { unsigned n = *(unsigned short*)td0_src; td0_src += 2; unsigned short data = *(unsigned short*)td0_src; for (; n; n--) *(unsigned short*)dst = data, dst += 2; break; } case 2: { unsigned short data; unsigned char s; do { switch (*td0_src++) { case 0: for (s = *td0_src++; s; s--) *dst++ = *td0_src++; break; case 1: s = *td0_src++; data = *(unsigned short*)td0_src; td0_src += 2; for (; s; s--) *(unsigned short*)dst = data, dst += 2; break; default: shit: delete snbuf; return false; // "bad TD0 file" } } while (td0_src < end_packed_data); break; } default: goto shit; } td0_dst += size; td0_src = end_packed_data; } } size = unsigned(td0_dst) - unsigned(data); delete snbuf; return true; } //---------------------------------------------------------------------------- // // TD0 CRC - table&proc grabed from TDCHECK.EXE by Alex Makeev // unsigned char tbltd0crc[512] = { 0x00,0x00,0xA0,0x97,0xE1,0xB9,0x41,0x2E,0x63,0xE5,0xC3,0x72,0x82,0x5C,0x22,0xCB, 0xC7,0xCA,0x67,0x5D,0x26,0x73,0x86,0xE4,0xA4,0x2F,0x04,0xB8,0x45,0x96,0xE5,0x01, 0x2F,0x03,0x8F,0x94,0xCE,0xBA,0x6E,0x2D,0x4C,0xE6,0xEC,0x71,0xAD,0x5F,0x0D,0xC8, 0xE8,0xC9,0x48,0x5E,0x09,0x70,0xA9,0xE7,0x8B,0x2C,0x2B,0xBB,0x6A,0x95,0xCA,0x02, 0x5E,0x06,0xFE,0x91,0xBF,0xBF,0x1F,0x28,0x3D,0xE3,0x9D,0x74,0xDC,0x5A,0x7C,0xCD, 0x99,0xCC,0x39,0x5B,0x78,0x75,0xD8,0xE2,0xFA,0x29,0x5A,0xBE,0x1B,0x90,0xBB,0x07, 0x71,0x05,0xD1,0x92,0x90,0xBC,0x30,0x2B,0x12,0xE0,0xB2,0x77,0xF3,0x59,0x53,0xCE, 0xB6,0xCF,0x16,0x58,0x57,0x76,0xF7,0xE1,0xD5,0x2A,0x75,0xBD,0x34,0x93,0x94,0x04, 0xBC,0x0C,0x1C,0x9B,0x5D,0xB5,0xFD,0x22,0xDF,0xE9,0x7F,0x7E,0x3E,0x50,0x9E,0xC7, 0x7B,0xC6,0xDB,0x51,0x9A,0x7F,0x3A,0xE8,0x18,0x23,0xB8,0xB4,0xF9,0x9A,0x59,0x0D, 0x93,0x0F,0x33,0x98,0x72,0xB6,0xD2,0x21,0xF0,0xEA,0x50,0x7D,0x11,0x53,0xB1,0xC4, 0x54,0xC5,0xF4,0x52,0xB5,0x7C,0x15,0xEB,0x37,0x20,0x97,0xB7,0xD6,0x99,0x76,0x0E, 0xE2,0x0A,0x42,0x9D,0x03,0xB3,0xA3,0x24,0x81,0xEF,0x21,0x78,0x60,0x56,0xC0,0xC1, 0x25,0xC0,0x85,0x57,0xC4,0x79,0x64,0xEE,0x46,0x25,0xE6,0xB2,0xA7,0x9C,0x07,0x0B, 0xCD,0x09,0x6D,0x9E,0x2C,0xB0,0x8C,0x27,0xAE,0xEC,0x0E,0x7B,0x4F,0x55,0xEF,0xC2, 0x0A,0xC3,0xAA,0x54,0xEB,0x7A,0x4B,0xED,0x69,0x26,0xC9,0xB1,0x88,0x9F,0x28,0x08, 0xD8,0x8F,0x78,0x18,0x39,0x36,0x99,0xA1,0xBB,0x6A,0x1B,0xFD,0x5A,0xD3,0xFA,0x44, 0x1F,0x45,0xBF,0xD2,0xFE,0xFC,0x5E,0x6B,0x7C,0xA0,0xDC,0x37,0x9D,0x19,0x3D,0x8E, 0xF7,0x8C,0x57,0x1B,0x16,0x35,0xB6,0xA2,0x94,0x69,0x34,0xFE,0x75,0xD0,0xD5,0x47, 0x30,0x46,0x90,0xD1,0xD1,0xFF,0x71,0x68,0x53,0xA3,0xF3,0x34,0xB2,0x1A,0x12,0x8D, 0x86,0x89,0x26,0x1E,0x67,0x30,0xC7,0xA7,0xE5,0x6C,0x45,0xFB,0x04,0xD5,0xA4,0x42, 0x41,0x43,0xE1,0xD4,0xA0,0xFA,0x00,0x6D,0x22,0xA6,0x82,0x31,0xC3,0x1F,0x63,0x88, 0xA9,0x8A,0x09,0x1D,0x48,0x33,0xE8,0xA4,0xCA,0x6F,0x6A,0xF8,0x2B,0xD6,0x8B,0x41, 0x6E,0x40,0xCE,0xD7,0x8F,0xF9,0x2F,0x6E,0x0D,0xA5,0xAD,0x32,0xEC,0x1C,0x4C,0x8B, 0x64,0x83,0xC4,0x14,0x85,0x3A,0x25,0xAD,0x07,0x66,0xA7,0xF1,0xE6,0xDF,0x46,0x48, 0xA3,0x49,0x03,0xDE,0x42,0xF0,0xE2,0x67,0xC0,0xAC,0x60,0x3B,0x21,0x15,0x81,0x82, 0x4B,0x80,0xEB,0x17,0xAA,0x39,0x0A,0xAE,0x28,0x65,0x88,0xF2,0xC9,0xDC,0x69,0x4B, 0x8C,0x4A,0x2C,0xDD,0x6D,0xF3,0xCD,0x64,0xEF,0xAF,0x4F,0x38,0x0E,0x16,0xAE,0x81, 0x3A,0x85,0x9A,0x12,0xDB,0x3C,0x7B,0xAB,0x59,0x60,0xF9,0xF7,0xB8,0xD9,0x18,0x4E, 0xFD,0x4F,0x5D,0xD8,0x1C,0xF6,0xBC,0x61,0x9E,0xAA,0x3E,0x3D,0x7F,0x13,0xDF,0x84, 0x15,0x86,0xB5,0x11,0xF4,0x3F,0x54,0xA8,0x76,0x63,0xD6,0xF4,0x97,0xDA,0x37,0x4D, 0xD2,0x4C,0x72,0xDB,0x33,0xF5,0x93,0x62,0xB1,0xA9,0x11,0x3E,0x50,0x10,0xF0,0x87, }; unsigned short TD0CRC(unsigned char *buf, unsigned int len) { unsigned short CRC = 0; int j; for (unsigned int i = 0; i < len; i++) { CRC ^= *buf++; j = CRC & 0xFF; CRC &= 0xFF00; CRC = (CRC << 8) | (CRC >> 8); CRC ^= ((unsigned short*)tbltd0crc)[j]; } return (CRC << 8) | (CRC >> 8); } // ---------------------------------------------------------------------------- unsigned char *packed_ptr, *packed_end; int readChar(void) { if (packed_ptr < packed_end) return *packed_ptr++; else return -1; } // ------------------------------------------------------ LZH unpacker unsigned char d_code[256] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0B, 0x0B, 0x0B, 0x0B, 0x0B, 0x0B, 0x0B, 0x0B, 0x0C, 0x0C, 0x0C, 0x0C, 0x0D, 0x0D, 0x0D, 0x0D, 0x0E, 0x0E, 0x0E, 0x0E, 0x0F, 0x0F, 0x0F, 0x0F, 0x10, 0x10, 0x10, 0x10, 0x11, 0x11, 0x11, 0x11, 0x12, 0x12, 0x12, 0x12, 0x13, 0x13, 0x13, 0x13, 0x14, 0x14, 0x14, 0x14, 0x15, 0x15, 0x15, 0x15, 0x16, 0x16, 0x16, 0x16, 0x17, 0x17, 0x17, 0x17, 0x18, 0x18, 0x19, 0x19, 0x1A, 0x1A, 0x1B, 0x1B, 0x1C, 0x1C, 0x1D, 0x1D, 0x1E, 0x1E, 0x1F, 0x1F, 0x20, 0x20, 0x21, 0x21, 0x22, 0x22, 0x23, 0x23, 0x24, 0x24, 0x25, 0x25, 0x26, 0x26, 0x27, 0x27, 0x28, 0x28, 0x29, 0x29, 0x2A, 0x2A, 0x2B, 0x2B, 0x2C, 0x2C, 0x2D, 0x2D, 0x2E, 0x2E, 0x2F, 0x2F, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F, }; unsigned char d_len[256] = { 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, }; const int N = 4096; // buffer size const int F = 60; // lookahead buffer size const int THRESHOLD = 2; const int NIL = N; // leaf of tree unsigned char text_buf[N + F - 1]; const int N_CHAR = (256 - THRESHOLD + F); // kinds of characters (character code = 0..N_CHAR-1) const int T = (N_CHAR * 2 - 1); // size of table const int R = (T - 1); // position of root const int MAX_FREQ = 0x8000; // updates tree when the // root frequency comes to this value. unsigned short freq[T + 1]; // frequency table short prnt[T + N_CHAR]; // pointers to parent nodes, except for the // elements [T..T + N_CHAR - 1] which are used to get // the positions of leaves corresponding to the codes. short son[T]; // pointers to child nodes (son[], son[] + 1) int r; unsigned getbuf; unsigned char getlen; int GetBit(void) /* get one bit */ { int i; while (getlen <= 8) { if ((i = readChar()) == -1) i = 0; getbuf |= i << (8 - getlen); getlen += 8; } i = getbuf; getbuf <<= 1; getlen--; return ((i >> 15) & 1); } int GetByte(void) /* get one byte */ { unsigned i; while (getlen <= 8) { if ((int)(i = readChar()) == -1) i = 0; getbuf |= i << (8 - getlen); getlen += 8; } i = getbuf; getbuf <<= 8; getlen -= 8; return (i >> 8) & 0xFF; } void StartHuff(void) { int i, j; getbuf = 0, getlen = 0; for (i = 0; i < N_CHAR; i++) { freq[i] = 1; son[i] = i + T; prnt[i + T] = i; } i = 0; j = N_CHAR; while (j <= R) { freq[j] = freq[i] + freq[i + 1]; son[j] = i; prnt[i] = prnt[i + 1] = j; i += 2; j++; } freq[T] = 0xffff; prnt[R] = 0; for (i = 0; i < N - F; i++) text_buf[i] = ' '; r = N - F; } /* reconstruction of tree */ void reconst(void) { int i, j, k; int f, l; /* collect leaf nodes in the first half of the table */ /* and replace the freq by (freq + 1) / 2. */ j = 0; for (i = 0; i < T; i++) { if (son[i] >= T) { freq[j] = (freq[i] + 1) / 2; son[j] = son[i]; j++; } } /* begin constructing tree by connecting sons */ for (i = 0, j = N_CHAR; j < T; i += 2, j++) { k = i + 1; f = freq[j] = freq[i] + freq[k]; for (k = j - 1; f < freq[k]; k--); k++; l = (j - k) * sizeof(*freq); memmove(&freq[k + 1], &freq[k], l); freq[k] = f; memmove(&son[k + 1], &son[k], l); son[k] = i; } /* connect prnt */ for (i = 0; i < T; i++) if ((k = son[i]) >= T) prnt[k] = i; else prnt[k] = prnt[k + 1] = i; } /* increment frequency of given code by one, and update tree */ void update(int c) { int i, j, k, l; if (freq[R] == MAX_FREQ) reconst(); c = prnt[c + T]; do { k = ++freq[c]; /* if the order is disturbed, exchange nodes */ if (k > freq[l = c + 1]) { while (k > freq[++l]); l--; freq[c] = freq[l]; freq[l] = k; i = son[c]; prnt[i] = l; if (i < T) prnt[i + 1] = l; j = son[l]; son[l] = i; prnt[j] = c; if (j < T) prnt[j + 1] = c; son[c] = j; c = l; } } while ((c = prnt[c]) != 0); /* repeat up to root */ } int DecodeChar(void) { int c; c = son[R]; /* travel from root to leaf, */ /* choosing the smaller child node (son[]) if the read bit is 0, */ /* the bigger (son[]+1} if 1 */ while (c < T) c = son[c + GetBit()]; c -= T; update(c); return c; } int DecodePosition(void) { int i, j, c; /* recover upper 6 bits from table */ i = GetByte(); c = (int)d_code[i] << 6; j = d_len[i]; /* read lower 6 bits verbatim */ j -= 2; while (j--) i = (i << 1) + GetBit(); return c | (i & 0x3f); } unsigned unpack_lzh(unsigned char *src, unsigned size, unsigned char *buf) { packed_ptr = src; packed_end = src + size; int i, j, k, c; unsigned count = 0; StartHuff(); // while (count < textsize) // textsize - sizeof unpacked data while (packed_ptr < packed_end) { c = DecodeChar(); if (c < 256) { *buf++ = c; text_buf[r++] = c; r &= (N - 1); count++; } else { i = (r - DecodePosition() - 1) & (N - 1); j = c - 255 + THRESHOLD; for (k = 0; k < j; k++) { c = text_buf[(i + k) & (N - 1)]; *buf++ = c; text_buf[r++] = c; r &= (N - 1); count++; } } } return count; } //-------------------------------------------------------------------------- int x2trd(const char *name, fileTYPE *f) { TDiskImage *img = new TDiskImage; img->Open(getFullPath(name), true); if (!FileOpenEx(f, "vtrd", -1)) { delete img; printf("ERROR: fail to create /vtrd\n"); return 0; } img->writeTRD(f->fd); delete(img); struct stat64 st; int ret = fstat64(f->fd, &st); if (ret < 0) { printf("x2trd(fstat) error: %d.\n", ret); FileClose(f); return 0; } f->size = st.st_size; FileSeekLBA(f, 0); printf("x2trd: vtrd size=%llu.\n", f->size); return 1; } int x2trd_ext_supp(const char *name) { const char *ext = ""; if (strlen(name) > 4) ext = name + strlen(name) - 4; return (!strcasecmp(ext, ".scl") || !strcasecmp(ext, ".fdi") || !strcasecmp(ext, ".udi")); }