Files
Main/DiskImage.cpp

3042 lines
124 KiB
C++
Raw Blame History

#include <unistd.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#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;
// <20><><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>...
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 <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>, <20><><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>...
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;
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD> 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++) // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
{
FTracksPtr[trk][side][0][tptr] = 0x4E;
FTracksPtr[trk][side][1][tptr++] = 0x00;
}
for (r = 0; r < 12; r++) // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
{
FTracksPtr[trk][side][0][tptr] = 0x00;
FTracksPtr[trk][side][1][tptr++] = 0x00;
}
ptrcrc = tptr;
for (r = 0; r < 3; r++) // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
{
FTracksPtr[trk][side][0][tptr] = 0xA1;
FTracksPtr[trk][side][1][tptr++] = 0xFF;
}
FTracksPtr[trk][side][0][tptr] = 0xFE; // <20><><EFBFBD><EFBFBD><EFBFBD> "<22><><EFBFBD><EFBFBD><EFBFBD>"
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++) // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
{
FTracksPtr[trk][side][0][tptr] = 0x4E;
FTracksPtr[trk][side][1][tptr++] = 0x00;
}
for (r = 0; r < 12; r++) // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
{
FTracksPtr[trk][side][0][tptr] = 0x00;
FTracksPtr[trk][side][1][tptr++] = 0x00;
}
ptrcrc = tptr;
for (r = 0; r < 3; r++) // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
{
FTracksPtr[trk][side][0][tptr] = 0xA1;
FTracksPtr[trk][side][1][tptr++] = 0xFF;
}
FTracksPtr[trk][side][0][tptr] = 0xFB; // <20><><EFBFBD><EFBFBD><EFBFBD> "<22><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>"
FTracksPtr[trk][side][1][tptr++] = 0x00;
for (r = 0; r < 256; r++) // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> 256<35><36><EFBFBD><EFBFBD>
{
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++) // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
{
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; // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> DataOffset
};
struct FDITRACKHDR
{
unsigned int DataOffset; // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>
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;
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>...
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; // "<22><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> 0 (<28><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>)"
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;
}
}
}
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD> <20> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> FDI <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>...
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;
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>:
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; // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
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 <20><><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD> <20> trkdatalen...
unsigned int FirstSpaceLen = 1;
unsigned int SecondSpaceLen = 1;
unsigned int ThirdSpaceLen = 1;
unsigned int SynchroSpaceLen = 1;
FreeSpace -= FirstSpaceLen + SecondSpaceLen + ThirdSpaceLen + SynchroSpaceLen;
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>:
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;
};
// <20><> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>...
if (FreeSpace >(SecCount * 2) + 10) { SynchroPulseLen++; FreeSpace -= SecCount; }
if (FreeSpace >(SecCount * 2) + 9) SynchroPulseLen++;
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>...
unsigned int tptr = 0;
for (unsigned sec = 0; sec < SecCount; sec++)
{
for (r = 0; r < FirstSpaceLen; r++) // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
{
FTracksPtr[trk][side][0][tptr] = 0x4E;
FTracksPtr[trk][side][1][tptr++] = 0x00;
}
for (r = 0; r < SynchroSpaceLen; r++) // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
{
FTracksPtr[trk][side][0][tptr] = 0x00;
FTracksPtr[trk][side][1][tptr++] = 0x00;
}
ptrcrc = tptr;
for (r = 0; r < SynchroPulseLen; r++) // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
{
FTracksPtr[trk][side][0][tptr] = 0xA1;
FTracksPtr[trk][side][1][tptr++] = 0xFF;
}
FTracksPtr[trk][side][0][tptr] = 0xFE; // <20><><EFBFBD><EFBFBD><EFBFBD> "<22><><EFBFBD><EFBFBD><EFBFBD>"
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++) // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
{
FTracksPtr[trk][side][0][tptr] = 0x4E;
FTracksPtr[trk][side][1][tptr++] = 0x00;
}
for (r = 0; r < SynchroSpaceLen; r++) // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
{
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 - <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>, 1 <20> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
// <20><><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>.
//
if (!(fdiSectorFlags & 0x40)) // oh-oh, data area not present... ;-)
{
ptrcrc = tptr;
for (r = 0; r < SynchroPulseLen; r++) // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
{
FTracksPtr[trk][side][0][tptr] = 0xA1;
FTracksPtr[trk][side][1][tptr++] = 0xFF;
}
if (fdiSectorFlags & 0x80)
FTracksPtr[trk][side][0][tptr] = 0xF8; // <20><><EFBFBD><EFBFBD><EFBFBD> "<22><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>"
else
FTracksPtr[trk][side][0][tptr] = 0xFB; // <20><><EFBFBD><EFBFBD><EFBFBD> "<22><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>"
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++) // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> SL <20><><EFBFBD><EFBFBD>
{
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++) // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
{
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;
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD> <20> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> FDD <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>...
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;
}
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>:
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 <20><><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD> <20> trkdatalen...
unsigned int FirstSpaceLen = 1;
unsigned int SecondSpaceLen = 1;
unsigned int ThirdSpaceLen = 1;
unsigned int SynchroSpaceLen = 1;
FreeSpace -= FirstSpaceLen + SecondSpaceLen + ThirdSpaceLen + SynchroSpaceLen;
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>:
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;
};
// <20><> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>...
if (FreeSpace >(SecCount * 2) + 10) { SynchroPulseLen++; FreeSpace -= SecCount; }
if (FreeSpace >(SecCount * 2) + 9) SynchroPulseLen++;
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>...
unsigned int tptr = 0;
for (unsigned sec = 0; sec < SecCount; sec++)
{
for (r = 0; r < FirstSpaceLen; r++) // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
{
FTracksPtr[trk][side][0][tptr] = 0x4E;
FTracksPtr[trk][side][1][tptr++] = 0x00;
}
for (r = 0; r < SynchroSpaceLen; r++) // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
{
FTracksPtr[trk][side][0][tptr] = 0x00;
FTracksPtr[trk][side][1][tptr++] = 0x00;
}
ptrcrc = tptr;
for (r = 0; r < SynchroPulseLen; r++) // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
{
FTracksPtr[trk][side][0][tptr] = 0xA1;
FTracksPtr[trk][side][1][tptr++] = 0xFF;
}
FTracksPtr[trk][side][0][tptr] = 0xFE; // <20><><EFBFBD><EFBFBD><EFBFBD> "<22><><EFBFBD><EFBFBD><EFBFBD>"
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++) // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
{
FTracksPtr[trk][side][0][tptr] = 0x4E;
FTracksPtr[trk][side][1][tptr++] = 0x00;
}
for (r = 0; r < SynchroSpaceLen; r++) // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
{
FTracksPtr[trk][side][0][tptr] = 0x00;
FTracksPtr[trk][side][1][tptr++] = 0x00;
}
// DATA AM
ptrcrc = tptr;
for (r = 0; r < SynchroPulseLen; r++) // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
{
FTracksPtr[trk][side][0][tptr] = 0xA1;
FTracksPtr[trk][side][1][tptr++] = 0xFF;
}
FTracksPtr[trk][side][0][tptr] = 0xFB; // <20><><EFBFBD><EFBFBD><EFBFBD> "<22><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>"
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++) // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> SL <20><><EFBFBD><EFBFBD>
{
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++) // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
{
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; // <20><><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD> <20><> 0 <20><> 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]; // <20><><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>
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;
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>:
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;
}
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>...
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 <20><><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD> <20> trkdatalen...
unsigned int FirstSpaceLen = 1;
unsigned int SecondSpaceLen = 1;
unsigned int ThirdSpaceLen = 1;
unsigned int SynchroSpaceLen = 1;
FreeSpace -= FirstSpaceLen + SecondSpaceLen + ThirdSpaceLen + SynchroSpaceLen;
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>:
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;
};
// <20><> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>...
if (FreeSpace >(SecCount * 2) + 10) { SynchroPulseLen++; FreeSpace -= SecCount; }
if (FreeSpace >(SecCount * 2) + 9) SynchroPulseLen++;
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>...
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++) // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
{
FTracksPtr[trk][side][0][tptr] = 0x4E;
FTracksPtr[trk][side][1][tptr++] = 0x00;
}
for (r = 0; r < SynchroSpaceLen; r++) // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
{
FTracksPtr[trk][side][0][tptr] = 0x00;
FTracksPtr[trk][side][1][tptr++] = 0x00;
}
ptrcrc = tptr;
for (r = 0; r < SynchroPulseLen; r++) // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
{
FTracksPtr[trk][side][0][tptr] = 0xA1;
FTracksPtr[trk][side][1][tptr++] = 0xFF;
}
FTracksPtr[trk][side][0][tptr] = 0xFE; // <20><><EFBFBD><EFBFBD><EFBFBD> "<22><><EFBFBD><EFBFBD><EFBFBD>"
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++) // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
{
FTracksPtr[trk][side][0][tptr] = 0x4E;
FTracksPtr[trk][side][1][tptr++] = 0x00;
}
for (r = 0; r < SynchroSpaceLen; r++) // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
{
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++) // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
{
FTracksPtr[trk][side][0][tptr] = 0xA1;
FTracksPtr[trk][side][1][tptr++] = 0xFF;
}
FTracksPtr[trk][side][0][tptr] = 0xFB; // <20><><EFBFBD><EFBFBD><EFBFBD> "<22><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>"
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++) // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> SL <20><><EFBFBD><EFBFBD>
{
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++) // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
{
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 ((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"));
}