/*
 * displaylink userspace controller demo 0.0.1
 * written 2008/09 by floe at butterbrot.org
 * in cooperation with chrisly at platon42.de
 * this code is released as public domain.
 *
 * this is so experimental that the warranty shot itself.
 * so don't expect any.
 *
 * build with "g++ -ggdb -Wall -o displaylink displaylink.c -lusb"
 *
 */

#include <usb.h>
#include <unistd.h>
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>


/******************* ENCRYPTION STUFF **********************/

unsigned char nullkey1[] = { 0x57, 0xCD, 0xDC, 0xA7, 0x1C, 0x88, 0x5E, 0x15, 0x60, 0xFE, 0xC6, 0x97, 0x16, 0x3D, 0x47, 0xF2 };
unsigned char nullkey2[] = { 0x47, 0x3D, 0x16, 0x97, 0xC6, 0xFE, 0x60, 0x15, 0x5E, 0x88, 0x1C, 0xA7, 0xDC, 0xB7, 0x6F, 0xF2 };
unsigned char nullkey3[] = { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0x18,0xF0 };

uint8_t  keybuffer[0x11000];
uint16_t ofsbuffer[0x1000];

// x^12+x^11+x^3+x^2+x+1 = 0001 1000 0000 1111 = 0x180F
int dl_crc12( unsigned char* data, int len) {
	int rem = 0;
	for (int i = 0; i < len; i++) {
		for (int j = 0; j < 8; j++) {
			rem = (rem << 1) | ((data[i] >> j) & 0x01);
			if (rem & 0x1000) rem = rem ^ 0x180F;
		}
	}
	return rem;
}


void dl_generate_key( uint8_t key[0x11000], uint16_t map[0x1000] ) {

  int coeffs[0x20];
  int count = 0;

  // loop1:
  for (int i = 0; i < 0x20; i++) {

    int tmp = 1 << i;
    if (!(tmp & 0x0829)) continue;

    coeffs[count] = i;
    count++;
  }

  int val = 0x01;

  // loop2:
  for (int i = 0; i < 0x11000; i++) {

    key[i] = val;
    if (i < 0x1000) map[val] = i;

    // loop3:
    for ( int j = 8; j > 0; j--) {

      int res = 0;

			// loop4:
      for (int k = 0; k < count; k++) {
        int coeff = coeffs[k];
        coeff = val >> coeff;
        res = res ^ coeff;
      }

      res = res & 1;
      res = res ^ (2*val);
      val = res & 0xFFF;
    }
  }
}


/******************* INITIALIZATION STUFF *****************/

uint8_t dl_peek( int addr, usb_dev_handle* handle, int timeout = 1000 ) {
	uint8_t buf[1];
	usb_control_msg( handle, 0xC0, 0x04, 0x00, addr, (char*)buf, 1, timeout );
	return buf[0];
}

void dl_poke( int addr, uint8_t value, usb_dev_handle* handle, int timeout = 1000 ) {
	usb_control_msg( handle, 0x40, 0x03, 0x00, addr, (char*)&value, 1, timeout );
}

int dl_poll( usb_dev_handle* handle, int timeout = 1000 ) {
	uint8_t buf[4];
	usb_control_msg( handle, 0xC0, 0x06, 0x00, 0x00, (char*)buf, 4, timeout );
	return (buf[3] << 24) | (buf[2] << 16) | (buf[1] << 8) | buf[0];
}

void dl_set_key( uint8_t key[16], usb_dev_handle* handle, int timeout = 1000 ) {
	usb_control_msg( handle, 0x40, 0x12, 0x00, 0x00, (char*)key, 16, timeout );
}

void dl_blink( usb_dev_handle* handle, int timeout = 1000 ) {
	usb_control_msg( handle, 0x40, 0x14, 0x00, 0x00, NULL, 0, timeout );
}

void dl_get_edid( uint8_t edid[128], usb_dev_handle* handle, int timeout = 1000 ) {
	uint8_t buf[64];
	int offset = 0;
	usb_control_msg( handle, 0xC0, 0x02, offset<<8, 0xA1, (char*)buf, 64, timeout ); memcpy( edid+offset, buf+1, 63 ); offset += 63;
	usb_control_msg( handle, 0xC0, 0x02, offset<<8, 0xA1, (char*)buf, 64, timeout ); memcpy( edid+offset, buf+1, 63 ); offset += 63;
	usb_control_msg( handle, 0xC0, 0x02, offset<<8, 0xA1, (char*)buf,  3, timeout ); memcpy( edid+offset, buf+1,  2 ); 
}

/******************* COMMAND BUFFER ***********************/

typedef struct {
	uint8_t* buffer;
	int pos, size;
} dl_cmdstream;


inline void create( dl_cmdstream* cs, int size ) {
	cs->buffer = (uint8_t*)malloc( size );
	cs->size = size;
	cs->pos = 0;
}

inline void destroy( dl_cmdstream* cs ) {
	free( cs->buffer );
	cs->size = 0;
}

inline void send( dl_cmdstream* cs, usb_dev_handle* handle, int ep = 1, int timeout = 1000 ) {
	usb_bulk_write( handle, ep, (char*)cs->buffer, cs->pos, timeout );
	cs->pos = 0;
}

inline void insertb( dl_cmdstream* cs, uint8_t val ) {
	cs->buffer[cs->pos++] = val;
}

inline void insertw( dl_cmdstream* cs, uint16_t val ) {
	insertb( cs, (val >> 8) & 0xFF );
	insertb( cs, (val     ) & 0xFF );
}

inline void inserta( dl_cmdstream* cs, uint32_t address ) {
	insertb( cs, (address >> 16) & 0xFF );
	insertb( cs, (address >>  8) & 0xFF );
	insertb( cs, (address      ) & 0xFF );
}

inline void insertd( dl_cmdstream* cs, uint32_t val ) {
	insertb( cs, (val >> 24) & 0xFF );
	insertb( cs, (val >> 16) & 0xFF );
	insertb( cs, (val >>  8) & 0xFF );
	insertb( cs, (val      ) & 0xFF );
}

inline void insert( dl_cmdstream* cs, int size, uint8_t* buf ) {
	memcpy( cs->buffer+cs->pos, buf, size );
	cs->pos += size;
}


/******************* COMMANDS *****************************/

#define DL_SOC  0xAF // start-of-command token

#define DL_SREG 0x20 // set register
#define DL_SYNC 0xA0 // sync/flush

#define DL_HUFF       0xE0       // set huffman table
#define DL_HUFF_MAGIC 0x263871CD // probably magic number

/******************* MISC COMMANDS ************************/

void dl_unknown_command( dl_cmdstream* cs ) {
	insertb( cs, DL_SOC );
	insertb( cs,   0x40 );
	insertb( cs,   0x0B );
}

void dl_sync_command( dl_cmdstream* cs ) {
	insertb( cs, DL_SOC  );
	insertb( cs, DL_SYNC );
}

void dl_decomp_table_command( dl_cmdstream* cs, int size, uint8_t* buf ) {

	if ((size % 9) != 0) return;
	int count = size / 9;

	insertb( cs, DL_SOC  );
	insertb( cs, DL_HUFF );

	insertd( cs, DL_HUFF_MAGIC ); // magic number
 	insertd( cs, count );         // count of 9-byte chunks

	insert( cs, size, buf ); // count * 9 bytes

	dl_sync_command( cs );
}


/******************* REGISTER COMMANDS ********************/

#define DL_REG_COLORDEPTH   0x00 // 0 = 16 bit, 1 = 24 bit
// 0x01 - 0x0E unknown
#define DL_REG_XRES_MSB     0x0F
#define DL_REG_XRES_LSB     0x10
// 0x11 - 0x16 unknown
#define DL_REG_YRES_MSB     0x17
#define DL_REG_YRES_LSB     0x18
// 0x19 - 0x1C unknown
// 0x1D - 0x1E unused
#define DL_REG_BLANK_SCREEN 0x1F // 0 = normal operation, 1 = blank screen
// 0x20 - 0xFE unused
#define DL_REG_SYNC         0xFF // 0 = hold register updates, 0xFF = resume

// The unknown registers very likely contain pixel clock, sync polarity etc.
// While the mapping hasn't been found yet, some default register sets for 
// standard resolutions are given below.

                                       // col   maybe horizontal clock   maybe vertical clock                                             xres                                              yres
uint8_t dl_register_init_640x480[]   = { 0x00,  0x99, 0x30, 0x26, 0x94,  0x60, 0xa9, 0xce, 0x60,  0x07, 0xb3, 0x0f, 0x79, 0xff, 0xff,  0x02, 0x80,  0x83, 0xbc, 0xff, 0xfc, 0xff, 0xff,  0x01, 0xe0,  0x01, 0x02,  0xab, 0x13 };
// 60 hz                                 0x01,  0x30, 0x1d, 0x94, 0x07,  0xa9, 0x55, 0x60, 0xef,  0x07, 0xb3, 0x0f, 0x79, 0xff, 0xff,  0x02, 0x80,  0x83, 0xbc, 0xff, 0xfc, 0xff, 0xff,  0x01, 0xe0,  ...........  0xab, 0x13
// 73 hz                                 0x01,  0x2b, 0xeb, 0x35, 0xd3,  0x0a, 0x95, 0xe6, 0x0e,  0x0f, 0xb5, 0x15, 0x2a, 0xff, 0xff,  0x02, 0x80,  0xcc, 0x1d, 0xff, 0xf9, 0xff, 0xff,  0x01, 0xe0,  ...........  0x9c, 0x18
// 75 hz                                 0x01,  0xeb, 0xf7, 0xd3, 0x0f,  0x4f, 0x93, 0xfa, 0x47,  0xb5, 0x58, 0xbf, 0x70, 0xff, 0xff,  0x02, 0x80,  0xf4, 0x8f, 0xff, 0xf9, 0xff, 0xff,  0x01, 0xe0,  ...........  0x9c, 0x18
// 85 hz                                 0x01,  0x93, 0x99, 0xd7, 0x26,  0x26, 0xc1, 0x8f, 0x9c,  0x0f, 0xb5, 0xb9, 0xbf, 0xff, 0xff,  0x02, 0x80,  0x1f, 0x39, 0xff, 0xf9, 0xff, 0xff,  0x01, 0xe0,  ...........  0x20, 0x1c

uint8_t dl_register_init_800x480[]   = { 0x00,  0x20, 0x3c, 0x7a, 0xc9,  0xf2, 0x6c, 0x48, 0xf9,  0x70, 0x53, 0xff, 0xff, 0x21, 0x27,  0x03, 0x20,  0x91, 0xf3, 0xff, 0xff, 0xff, 0xf9,  0x01, 0xe0,  0x01, 0x02,  0xc8, 0x19 };
// 60 hz                                 0x01,  0xff, 0x29, 0x66, 0x6b,  0xfe, 0x53, 0x13, 0x3e,  0xd3, 0x0f, 0xff, 0xff, 0xff, 0xf9,  0x03, 0x20,  0x33, 0xe9, 0xff, 0xff, 0xff, 0xfe,  0x01, 0xe0,  ...........  0x24, 0x13

uint8_t dl_register_init_800x600[]   = { 0x00,  0x20, 0x3c, 0x7a, 0xc9,  0x93, 0x60, 0xc8, 0xc7,  0x70, 0x53, 0xff, 0xff, 0x21, 0x27,  0x03, 0x20,  0x91, 0x8f, 0xff, 0xff, 0xff, 0xf2,  0x02, 0x58,  0x01, 0x02,  0x40, 0x1f };
// 56 hz                                 0x01,  0x65, 0x35, 0x48, 0xf4,  0xf2, 0x6c, 0x19, 0x18,  0xc9, 0x4b, 0xff, 0xff, 0x70, 0x35,  0x03, 0x20,  0x32, 0x31, 0xff, 0xff, 0xff, 0xfc,  0x02, 0x58,  ...........  0x20, 0x1c
// 60 hz                                 0x01,  0x20, 0x3c, 0x7a, 0xc9,  0x93, 0x60, 0xc8, 0xc7,  0x70, 0x53, 0xff, 0xff, 0x21, 0x27,  0x03, 0x20,  0x91, 0x8f, 0xff, 0xff, 0xff, 0xf2,  0x02, 0x58,  ...........  0x40, 0x1f
// 72 hz                                 0x01,  0xeb, 0xf7, 0xd1, 0x90,  0x4d, 0x82, 0x23, 0x1f,  0x39, 0xcf, 0xff, 0xff, 0x43, 0x21,  0x03, 0x20,  0x62, 0xc5, 0xff, 0xff, 0xff, 0xca,  0x02, 0x58,  ...........  0x10, 0x27
// 75 hz                                 0x01,  0xb3, 0x76, 0x39, 0xcf,  0xf2, 0x6c, 0x19, 0x18,  0x70, 0x53, 0xff, 0xff, 0x35, 0x33,  0x03, 0x20,  0x32, 0x31, 0xff, 0xff, 0xff, 0xf9,  0x02, 0x58,  ...........  0xac, 0x26
// 85 hz                                 0x01,  0x20, 0x3c, 0x7a, 0xc9,  0x9b, 0x05, 0x46, 0x3f,  0xcf, 0x70, 0xff, 0xff, 0xbf, 0x70,  0x03, 0x20,  0x8c, 0x7f, 0xff, 0xff, 0xff, 0xf9,  0x02, 0x58,  ...........  0xf2, 0x2b

uint8_t dl_register_init_1024x768[]  = { 0x00,  0x36, 0x18, 0xd5, 0x10,  0x60, 0xa9, 0x7b, 0x33,  0xa1, 0x2b, 0x27, 0x32, 0xff, 0xff,  0x04, 0x00,  0xd9, 0x9a, 0xff, 0xca, 0xff, 0xff,  0x03, 0x00,  0x04, 0x03,  0xc8, 0x32 };
// 60 hz                                 0x01,  0x36, 0x18, 0xd5, 0x10,  0x60, 0xa9, 0x7b, 0x33,  0xa1, 0x2b, 0x27, 0x32, 0xff, 0xff,  0x04, 0x00,  0xd9, 0x9a, 0xff, 0xca, 0xff, 0xff,  0x03, 0x00,  ...........  0xc8, 0x32
// 70 hz                                 0x01,  0xb4, 0xed, 0x4c, 0x5e,  0x60, 0xa9, 0x7b, 0x33,  0x10, 0x4d, 0x27, 0x32, 0xff, 0xff,  0x04, 0x00,  0xd9, 0x9a, 0xff, 0xca, 0xff, 0xff,  0x03, 0x00,  ...........  0x98, 0x3a
// 75 hz                                 0x01,  0xec, 0xb4, 0xa0, 0x4c,  0x36, 0x0a, 0x07, 0xb3,  0x5e, 0xd5, 0xff, 0xff, 0x0f, 0x79,  0x04, 0x00,  0x0f, 0x66, 0xff, 0xff, 0xff, 0xf9,  0x03, 0x00,  ...........  0x86, 0x3d
// 85 hz                                 0x01,  0x18, 0xdc, 0x10, 0x4d,  0x0a, 0x95, 0xb3, 0x35,  0x79, 0x01, 0xff, 0xff, 0x0f, 0x79,  0x04, 0x00,  0x66, 0x6b, 0xff, 0xff, 0xff, 0xf9,  0x03, 0x00,  ...........  0xd4, 0x49

uint8_t dl_register_init_1280x1024[] = { 0x00,  0x98, 0xf8, 0x0d, 0x57,  0x2a, 0x55, 0x4d, 0x54,  0xca, 0x0d, 0xff, 0xff, 0x94, 0x43,  0x05, 0x00,  0x9a, 0xa8, 0xff, 0xff, 0xff, 0xf9,  0x04, 0x00,  0x04, 0x02,  0x60, 0x54 };
// 60 hz                                 0x01,  0x98, 0xf8, 0x0d, 0x57,  0x2a, 0x55, 0x4d, 0x54,  0xca, 0x0d, 0xff, 0xff, 0x94, 0x43,  0x05, 0x00,  0x9a, 0xa8, 0xff, 0xff, 0xff, 0xf9,  0x04, 0x00,  ...........  0x60, 0x54
// 75 hz                                 0x01,  0xce, 0x12, 0x3f, 0x9f,  0x2a, 0x55, 0x4d, 0x54,  0xca, 0x0d, 0xff, 0xff, 0x32, 0x60,  0x05, 0x00,  0x9a, 0xa8, 0xff, 0xff, 0xff, 0xf9,  0x04, 0x00,  ...........  0x78, 0x69
// 85 hz                                 0x01,  0x24, 0xce, 0x77, 0x3f,  0x95, 0x5c, 0x55, 0x1f,  0x9e, 0x64, 0xff, 0xff, 0x3a, 0x66,  0x05, 0x00,  0xaa, 0x3f, 0xff, 0xff, 0xff, 0xf9,  0x04, 0x00,  ...........  0x0c, 0x7b

// 1360x768 60 hz                        0x01,  0xf8, 0x42, 0x9e, 0x64,  0xf2, 0x6c, 0x28, 0x0f,  0xe8, 0x61, 0xff, 0xff, 0x94, 0x43,  0x05, 0x50,  0x40, 0x7b, 0xff, 0xff, 0xff, 0xca,  0x03, 0x00,  ...........  0xcc, 0x42
// 1366x768 60 hz                        0x01,  0x19, 0x1e, 0x1f, 0xb0,  0x93, 0x60, 0x40, 0x7b,  0x36, 0xe8, 0x27, 0x32, 0xff, 0xff,  0x05, 0x56,  0x03, 0xd9, 0xff, 0xff, 0xfc, 0xa7,  0x03, 0x00,  ...........  0x9a, 0x42
// 1400x1050 60 hz                       0x01,  0x42, 0x24, 0x38, 0x36,  0xc1, 0x52, 0xd9, 0x29,  0xea, 0xb8, 0x32, 0x60, 0xff, 0xff,  0x05, 0x78,  0xc9, 0x4e, 0xff, 0xff, 0xff, 0xf2,  0x04, 0x1a,  ...........  0x1e, 0x5f
// 1400x1050 60 hz                       0x01,  0xca, 0x21, 0x90, 0x9f,  0x93, 0x60, 0x47, 0xec,  0xd5, 0x03, 0xff, 0xff, 0x6c, 0x15,  0x05, 0x78,  0x3f, 0x64, 0xff, 0xf2, 0xff, 0xff,  0x04, 0x1a,  ...........  0xe8, 0x4e

// DL-160:
// 1600x1200 60 hz                       0x01,  0xcf, 0xa4, 0x3c, 0x4e,  0x55, 0x73, 0x71, 0x2b,  0x71, 0x52, 0xff, 0xff, 0xee, 0xca,  0x06, 0x40,  0xe2, 0x57, 0xff, 0xff, 0xff, 0xf9,  0x04, 0xb0,  ...........  0x90, 0x7e
// 1920x1080 60 hz                       0x01,  0x73, 0xa6, 0x28, 0xb3,  0x54, 0xaa, 0x41, 0x5d,  0x0d, 0x9f, 0x32, 0x60, 0xff, 0xff,  0x07, 0x80,  0x0a, 0xea, 0xff, 0xf9, 0xff, 0xff,  0x04, 0x38,  ...........  0xe0, 0x7c

/*24-bit:
640x480:    01    99 30 26 94 60 a9 ce 60 07 b3 0f 79 ff ff  02 80  83 bc ff fc ff ff  01 e0  01 02 ab 13 
1280x..:    01    98 f8 0d 57 2a 55 4d 54 ca 0d ff ff 94 43  05 00  9a a8 ff ff ff f9  04 00  04 02 60 54 
*/

void dl_set_register( dl_cmdstream* cs, uint8_t reg, uint8_t val ) {
	insertb( cs, DL_SOC  );
	insertb( cs, DL_SREG );
	insertb( cs,     reg );
	insertb( cs,     val );
}

void dl_set_registers( dl_cmdstream* cs, uint8_t values[0x1D] ) {
	dl_set_register( cs, DL_REG_SYNC, 0x00 );
	for (int i = 0; i < 0x1D; i++)
		dl_set_register( cs, i, values[i] );
	dl_set_register( cs, DL_REG_SYNC, 0xFF );
}


/****************** ADDRESS REGISTERS *********************/

#define DL_ADDR_FB16_START  0x20 // 16-bit mode, color MSBs, RGB 565
#define DL_ADDR_FB16_STRIDE 0x23
#define DL_ADDR_FB8_START   0x26 // additional 8 bit for 24-bit mode, color LSBs, RGB 323?
#define DL_ADDR_FB8_STRIDE  0x29

void dl_set_address( dl_cmdstream* cs, uint8_t reg, int address ) {
	dl_set_register( cs, reg+0, (address >> 16) & 0xFF );
	dl_set_register( cs, reg+1, (address >>  8) & 0xFF );
	dl_set_register( cs, reg+2, (address      ) & 0xFF );
}

void dl_set_offsets( dl_cmdstream* cs, int start16, int stride16, int start8, int stride8 ) {
	dl_set_register( cs, DL_REG_SYNC, 0x00 );
	dl_set_address( cs, DL_ADDR_FB16_START,  start16  );
	dl_set_address( cs, DL_ADDR_FB16_STRIDE, stride16 );
	dl_set_address( cs, DL_ADDR_FB8_START,   start8   );
	dl_set_address( cs, DL_ADDR_FB8_STRIDE,  stride8  );
	dl_set_register( cs, DL_REG_SYNC, 0xFF );
}


/******************* GRAPHICS COMMANDS ********************/

#define DL_GFX_BASE 0x60 // base graphics command
#define DL_GFX_WORD 0x08 // word-mode flag
#define DL_GFX_COMP 0x10 // compressed-mode flag

#define DL_GFX_WRITE (DL_GFX_BASE | 0x00) // write memory
#define DL_GFX_RLE   (DL_GFX_BASE | 0x01) // write RLE-encoded data
#define DL_GFX_COPY  (DL_GFX_BASE | 0x02) // internal copy

void dl_gfx_command( dl_cmdstream* cs, uint8_t cmd, int addr, uint8_t count ) {
	insertb( cs, DL_SOC );
	insertb( cs,    cmd );
	inserta( cs,   addr );
	insertb( cs,  count );
}

void dl_gfx_write( dl_cmdstream* cs, int addr, uint8_t count, uint8_t* data ) {
	dl_gfx_command( cs, DL_GFX_WRITE | DL_GFX_WORD, addr, count );
	int pcount = (count == 0) ? 256 : count;
	insert( cs, pcount*2, data );
}

typedef struct {
	uint8_t count;
	uint16_t value;
} rle_word;

void dl_gfx_rle( dl_cmdstream* cs, int addr, uint8_t count, rle_word* rs ) {

	dl_gfx_command( cs, DL_GFX_RLE | DL_GFX_WORD, addr, count );

	int pcount = (count == 0) ? 256 : count;
	int i = 0;
	rle_word* cur = rs;

	while (i < pcount) {
		insertb( cs, cur->count );
		insertw( cs, cur->value );
		i += (cur->count == 0) ? 256: cur->count;
		cur++;
	}
}

void dl_gfx_copy( dl_cmdstream* cs, int src_addr, int dst_addr, uint8_t count ) {
	dl_gfx_command( cs, DL_GFX_COPY | DL_GFX_WORD, dst_addr, count );
  inserta( cs, src_addr );
}


/******************* INITIALIZATION SEQUENCE **************/

static uint8_t dl_decomp_table[] = {
	0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
	0x00, 0x00, 0x01, 0x60, 0x01, 0x00, 0x00, 0x00, 0x61,
	0x00, 0x00, 0x00, 0x01, 0x23, 0x00, 0x00, 0x00, 0x01,
	0x00, 0x00, 0x01, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01,
	0x00, 0x00, 0x01, 0x60, 0x05, 0x00, 0x00, 0x00, 0x61,
	0x00, 0x00, 0x00, 0x01, 0x67, 0x00, 0x01, 0x00, 0x01,
	0xff, 0xff, 0xff, 0x7f, 0xff, 0xff, 0xff, 0xff, 0x7f,
	0xff, 0xff, 0xff, 0x7f, 0xff, 0xff, 0xff, 0xff, 0x7f,
	0x00, 0x00, 0x00, 0x01, 0x89, 0x00, 0x00, 0x00, 0x01,
	0x00, 0x00, 0x00, 0x61, 0xab, 0x00, 0x00, 0x00, 0x61,
	0x00, 0x00, 0x00, 0x01, 0xcd, 0x00, 0x00, 0x00, 0x01,
	0x00, 0x00, 0x01, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x01,
	0x00, 0x00, 0x01, 0x60, 0x0f, 0x00, 0x00, 0x00, 0x61,
	0xff, 0xff, 0xff, 0x7f, 0xff, 0xff, 0xff, 0xff, 0x7f,
	0xff, 0xff, 0xff, 0x7f, 0xff, 0xff, 0xff, 0xff, 0x7f,
	0xff, 0xff, 0xff, 0x7f, 0xff, 0xff, 0xff, 0xff, 0x7f,
	0x00, 0x00, 0x00, 0x02, 0x01, 0x00, 0x00, 0x00, 0x02,
	0x00, 0x00, 0x00, 0x02, 0x01, 0x00, 0x00, 0x00, 0x02,
	0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
	0x00, 0x00, 0x01, 0x01, 0x22, 0x00, 0x00, 0x01, 0x02,
	0x00, 0x00, 0x00, 0x02, 0x33, 0x00, 0x01, 0x00, 0x02,
	0x00, 0x00, 0x00, 0x02, 0x01, 0x00, 0x00, 0x00, 0x02,
	0x00, 0x00, 0x00, 0x02, 0x44, 0x00, 0x02, 0x00, 0x02,
	0x00, 0x00, 0x00, 0x02, 0x44, 0x00, 0x02, 0x00, 0x02,
	0x00, 0x00, 0x01, 0x00, 0x05, 0x00, 0x00, 0x00, 0x02,
	0x00, 0x00, 0x00, 0x02, 0x67, 0x00, 0x00, 0x00, 0x02,
	0x00, 0x00, 0x01, 0x00, 0x05, 0x00, 0x00, 0x00, 0x02,
	0x00, 0x00, 0x00, 0x02, 0x67, 0x00, 0x00, 0x00, 0x02,
	0x00, 0x00, 0x00, 0x02, 0x5b, 0x00, 0x00, 0x00, 0x01,
	0x00, 0x00, 0x01, 0x01, 0xc8, 0x00, 0x00, 0x01, 0x02,
	0x00, 0x00, 0x00, 0x02, 0x5b, 0x00, 0x00, 0x00, 0x01,
	0x00, 0x00, 0x00, 0x02, 0x5b, 0x00, 0x00, 0x00, 0x01,
	0x00, 0x00, 0x00, 0x02, 0x9a, 0x00, 0x00, 0x00, 0x02,
	0x00, 0x00, 0x00, 0x02, 0x33, 0x00, 0x01, 0x00, 0x02,
	0x00, 0x00, 0x01, 0x01, 0x2b, 0x00, 0x00, 0x01, 0x02,
	0x00, 0x00, 0x00, 0x02, 0xcc, 0x00, 0x02, 0x00, 0x02,
	0x00, 0x00, 0x00, 0x02, 0xdd, 0x00, 0x04, 0x00, 0x02,
	0x00, 0x00, 0x00, 0x02, 0xef, 0x00, 0x00, 0x00, 0x02,
	0x00, 0x00, 0x00, 0x03, 0x01, 0x00, 0x00, 0x00, 0x03,
	0x00, 0x00, 0x00, 0x03, 0x23, 0x00, 0x00, 0x00, 0x03,
	0x00, 0x00, 0x01, 0x01, 0xc4, 0x00, 0x00, 0x01, 0x03,
	0x00, 0x29, 0x01, 0x00, 0x05, 0x00, 0x00, 0x00, 0x03,
	0x00, 0xb7, 0x01, 0x00, 0x06, 0x00, 0x00, 0x00, 0x03,
	0x00, 0x00, 0x00, 0x03, 0x78, 0x00, 0x00, 0x00, 0x03,
	0x00, 0x00, 0x00, 0x03, 0x99, 0x00, 0x04, 0x00, 0x03,
	0x00, 0x00, 0x00, 0x03, 0xaa, 0x00, 0x08, 0x00, 0x03,
	0x00, 0x00, 0x00, 0x03, 0xbc, 0x00, 0x00, 0x00, 0x03,
	0x00, 0x00, 0x00, 0x03, 0xde, 0x00, 0x00, 0x00, 0x03,
	0x00, 0x00, 0x00, 0x03, 0xf0, 0x00, 0x00, 0x00, 0x04,
	0x00, 0x00, 0x00, 0x04, 0x12, 0x00, 0x00, 0x00, 0x04,
	0x00, 0x00, 0x00, 0x04, 0x34, 0x00, 0x00, 0x00, 0x04,
	0x00, 0x00, 0x00, 0x04, 0x56, 0x00, 0x00, 0x00, 0x04,
	0x00, 0x00, 0x00, 0x04, 0x78, 0x00, 0x00, 0x00, 0x04,
	0x00, 0x00, 0x00, 0x04, 0x9a, 0x00, 0x00, 0x00, 0x04,
	0x00, 0xd7, 0x01, 0x00, 0x00, 0x00, 0x09, 0x01, 0x00,
	0x00, 0x00, 0x01, 0x01, 0x22, 0x00, 0x00, 0x02, 0x01,
	0x00, 0x00, 0x02, 0x04, 0xbb, 0x00, 0x00, 0x03, 0x04,
	0x00, 0x00, 0x00, 0x04, 0xcc, 0x00, 0x08, 0x00, 0x04,
	0x00, 0x00, 0x00, 0x04, 0xdd, 0x00, 0x10, 0x00, 0x04,
	0x00, 0x20, 0x01, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x04,
	0x00, 0x00, 0x00, 0x04, 0xf0, 0x00, 0x00, 0x00, 0x05,
	0xff, 0xe0, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x05,
	0x00, 0x00, 0x00, 0x05, 0x23, 0x00, 0x00, 0x00, 0x05,
	0x08, 0x00, 0x01, 0x00, 0x00, 0x08, 0x20, 0x01, 0x00,
	0x00, 0x00, 0x00, 0x05, 0x45, 0x00, 0x00, 0x00, 0x05,
	0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x21, 0x01, 0x00,
	0x00, 0x00, 0x00, 0x05, 0x67, 0x00, 0x00, 0x00, 0x05,
	0xf8, 0x00, 0x01, 0x00, 0x00, 0xf7, 0xe0, 0x01, 0x00,
	0x00, 0x00, 0x00, 0x05, 0x89, 0x00, 0x00, 0x00, 0x05,
	0xff, 0xff, 0x01, 0x00, 0x00, 0xff, 0xdf, 0x01, 0x00,
	0x00, 0x00, 0x00, 0x05, 0xab, 0x00, 0x00, 0x00, 0x05,
	0x00, 0x00, 0x01, 0x01, 0xcc, 0x00, 0x00, 0x02, 0x01,
	0x00, 0x00, 0x02, 0x05, 0xcc, 0x00, 0x00, 0x03, 0x05,
	0x00, 0x12, 0x01, 0x00, 0x00, 0x00, 0x32, 0x01, 0x00,
	0x00, 0xce, 0x01, 0x00, 0x00, 0x00, 0xae, 0x01, 0x00,
	0x00, 0x00, 0x00, 0x05, 0xde, 0x00, 0x00, 0x00, 0x05,
	0x00, 0x00, 0x00, 0x05, 0xff, 0x00, 0x10, 0x00, 0x05,
	0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x20, 0x00, 0x06,
	0x08, 0x41, 0x01, 0x00, 0x00, 0x08, 0x21, 0x01, 0x00,
	0x08, 0x61, 0x00, 0x06, 0x12, 0x00, 0x00, 0x00, 0x06,
	0x00, 0x00, 0x00, 0x06, 0x34, 0x00, 0x00, 0x00, 0x06,
	0xf7, 0xbf, 0x01, 0x00, 0x00, 0xf7, 0xdf, 0x01, 0x00,
	0xf7, 0x9f, 0x00, 0x06, 0x56, 0x00, 0x00, 0x00, 0x06,
	0x00, 0x00, 0x00, 0x06, 0x78, 0x00, 0x00, 0x00, 0x06,
	0x10, 0x61, 0x00, 0x06, 0x9a, 0x00, 0x00, 0x00, 0x06,
	0x00, 0x41, 0x00, 0x06, 0x9b, 0x00, 0x00, 0x00, 0x06,
	0x08, 0x62, 0x00, 0x06, 0x9c, 0x00, 0x00, 0x00, 0x06,
	0x08, 0x40, 0x00, 0x06, 0x9d, 0x00, 0x00, 0x00, 0x06,
	0xef, 0x9f, 0x00, 0x06, 0xef, 0x00, 0x00, 0x00, 0x06,
	0xff, 0xbf, 0x00, 0x06, 0xe0, 0x00, 0x00, 0x00, 0x07,
	0xf7, 0x9e, 0x00, 0x06, 0xe1, 0x00, 0x00, 0x00, 0x07,
	0xf7, 0xc0, 0x00, 0x06, 0xe2, 0x00, 0x00, 0x00, 0x07,
	0x00, 0x00, 0x00, 0x07, 0x34, 0x00, 0x00, 0x00, 0x07,
	0x00, 0x00, 0x01, 0x01, 0x22, 0x00, 0x00, 0x03, 0x01,
	0x00, 0x00, 0x04, 0x07, 0x55, 0x00, 0x00, 0x06, 0x07,
	0x00, 0x00, 0x00, 0x07, 0x66, 0x00, 0x20, 0x00, 0x07,
	0x00, 0x00, 0x00, 0x07, 0x77, 0x00, 0x40, 0x00, 0x07,
	0x00, 0x00, 0x00, 0x07, 0x88, 0x00, 0x20, 0x00, 0x07,
	0x08, 0x01, 0x01, 0x00, 0x09, 0x10, 0x02, 0x00, 0x07,
	0xef, 0xfe, 0x00, 0x07, 0xab, 0x00, 0x00, 0x00, 0x07,
	0x00, 0x00, 0x00, 0x07, 0xcf, 0xff, 0xff, 0xff, 0x7f,
	0x00, 0x00, 0x00, 0x07, 0xdd, 0xff, 0xe0, 0x00, 0x07,
	0xf7, 0xff, 0x01, 0x00, 0x0e, 0xef, 0xfe, 0x00, 0x07,
	0x10, 0x02, 0x00, 0x07, 0xf0, 0x00, 0x00, 0x00, 0x08,
	0x00, 0x00, 0x00, 0x08, 0x1f, 0xff, 0xff, 0xff, 0x7f,
	0x00, 0x00, 0x01, 0x00, 0x02, 0x08, 0x41, 0x00, 0x08,
	0x10, 0x41, 0x00, 0x06, 0x93, 0x00, 0x00, 0x00, 0x08,
	0x00, 0x00, 0x00, 0x08, 0x45, 0x00, 0x00, 0x00, 0x08,
	0x08, 0x42, 0x00, 0x06, 0x96, 0x00, 0x00, 0x00, 0x08,
	0x00, 0x00, 0x00, 0x08, 0x78, 0x00, 0x00, 0x00, 0x08,
	0x00, 0x00, 0x01, 0x00, 0x09, 0xf7, 0xbf, 0x00, 0x08,
	0xef, 0xbf, 0x00, 0x06, 0xea, 0x00, 0x00, 0x00, 0x08,
	0x00, 0x00, 0x00, 0x08, 0xbc, 0x00, 0x00, 0x00, 0x08,
	0xf7, 0xbe, 0x00, 0x06, 0xed, 0x00, 0x00, 0x00, 0x08,
	0x00, 0x00, 0x00, 0x08, 0xef, 0x00, 0x00, 0x00, 0x08,
	0x00, 0x00, 0x01, 0x01, 0xcc, 0x00, 0x00, 0x03, 0x01,
	0x00, 0x00, 0x04, 0x09, 0x00, 0x00, 0x00, 0x06, 0x09,
	0x00, 0x00, 0x00, 0x09, 0x12, 0x00, 0x00, 0x00, 0x09,
	0x00, 0x00, 0x00, 0x09, 0x33, 0x00, 0x40, 0x00, 0x09,
	0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x80, 0x04, 0x00,
	0x00, 0x00, 0x01, 0x00, 0x04, 0x08, 0x41, 0x00, 0x09,
	0x00, 0x00, 0x00, 0x09, 0x55, 0x08, 0x01, 0x00, 0x09,
	0x00, 0x00, 0x00, 0x09, 0x66, 0xf7, 0xff, 0x00, 0x09,
	0x10, 0x42, 0x00, 0x06, 0x99, 0x10, 0x62, 0x00, 0x06,
	0xf8, 0x1f, 0x00, 0x06, 0x99, 0x00, 0x40, 0x00, 0x06,
	0x00, 0x00, 0x01, 0x00, 0x07, 0xf7, 0xbf, 0x00, 0x09,
	0x00, 0x00, 0x00, 0x09, 0x88, 0xf7, 0xff, 0x00, 0x09,
	0x00, 0x00, 0x00, 0x09, 0x99, 0x08, 0x01, 0x00, 0x09,
	0xef, 0xbe, 0x00, 0x06, 0xee, 0xef, 0x9e, 0x00, 0x06,
	0x07, 0xe1, 0x00, 0x06, 0xee, 0xff, 0xc0, 0x00, 0x06,
	0x00, 0x00, 0x01, 0x00, 0x0a, 0x08, 0x41, 0x00, 0x09,
	0xf8, 0x20, 0x00, 0x06, 0x99, 0x07, 0xff, 0x00, 0x06,
	0x08, 0x1f, 0x00, 0x06, 0x9b, 0x00, 0x00, 0x00, 0x09,
	0x00, 0x00, 0x00, 0x09, 0xcd, 0x00, 0x00, 0x00, 0x09,
	0x00, 0x1f, 0x00, 0x06, 0x99, 0xf8, 0x01, 0x00, 0x06,
	0xf8, 0x21, 0x00, 0x06, 0x9e, 0x00, 0x00, 0x00, 0x09,
	0x00, 0x00, 0x00, 0x09, 0xf0, 0x00, 0x00, 0x00, 0x0a,
	0x00, 0x00, 0x01, 0x00, 0x01, 0xf7, 0xbf, 0x00, 0x0a,
	0x07, 0xe0, 0x00, 0x06, 0xee, 0xf8, 0x01, 0x00, 0x06,
	0xf7, 0xe1, 0x00, 0x06, 0xe2, 0x00, 0x00, 0x00, 0x0a,
	0x00, 0x00, 0x00, 0x0a, 0x34, 0x00, 0x00, 0x00, 0x0a,
	0xff, 0xe1, 0x00, 0x06, 0xee, 0x07, 0xff, 0x00, 0x06,
	0x07, 0xdf, 0x00, 0x06, 0xe5, 0x00, 0x00, 0x00, 0x0a,
	0x00, 0x00, 0x00, 0x0a, 0x67, 0x00, 0x00, 0x00, 0x0a,
	0x00, 0x00, 0x00, 0x0a, 0x89, 0x00, 0x00, 0x00, 0x0a,
	0x00, 0x00, 0x01, 0x01, 0x22, 0x00, 0x00, 0x05, 0x01,
	0x00, 0x00, 0x08, 0x0a, 0xaa, 0x00, 0x00, 0x0c, 0x0a,
	0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x80, 0x01, 0x00,
	0x00, 0x00, 0x00, 0x0a, 0xbb, 0x08, 0x41, 0x00, 0x0a,
	0x00, 0x00, 0x00, 0x0a, 0xcd, 0x10, 0x02, 0x00, 0x0a,
	0x00, 0x00, 0x00, 0x0a, 0xce, 0xef, 0xfe, 0x00, 0x0a,
	0x00, 0x00, 0x00, 0x0a, 0xff, 0xf7, 0xbf, 0x00, 0x0a,
	0x00, 0x00, 0x00, 0x0b, 0x01, 0xef, 0xfe, 0x00, 0x0b,
	0x00, 0x00, 0x00, 0x0b, 0x02, 0x10, 0x02, 0x00, 0x0b,
	0x00, 0x00, 0x01, 0x00, 0x03, 0x08, 0x41, 0x00, 0x0b,
	0x10, 0x21, 0x00, 0x06, 0x94, 0x00, 0x00, 0x00, 0x0b,
	0xef, 0xff, 0x00, 0x06, 0x95, 0x00, 0x00, 0x00, 0x0b,
	0x00, 0x00, 0x00, 0x0b, 0x66, 0x00, 0x20, 0x00, 0x0b,
	0x08, 0x22, 0x00, 0x06, 0x97, 0x00, 0x00, 0x00, 0x0b,
	0xf7, 0xfe, 0x00, 0x06, 0x98, 0x00, 0x00, 0x00, 0x0b,
	0x00, 0x00, 0x00, 0x0b, 0x99, 0x00, 0x20, 0x00, 0x0b,
	0x00, 0x00, 0x01, 0x00, 0x0a, 0xf7, 0xbf, 0x00, 0x0b,
	0xef, 0xdf, 0x00, 0x06, 0xeb, 0x00, 0x00, 0x00, 0x0b,
	0x10, 0x01, 0x00, 0x06, 0xec, 0x00, 0x00, 0x00, 0x0b,
	0x00, 0x00, 0x00, 0x0b, 0xdd, 0xff, 0xe0, 0x00, 0x0b,
	0xf7, 0xde, 0x00, 0x06, 0xee, 0x00, 0x00, 0x00, 0x0b,
	0x08, 0x02, 0x00, 0x06, 0xef, 0x00, 0x00, 0x00, 0x0b,
	0x00, 0x00, 0x00, 0x0c, 0x00, 0xff, 0xe0, 0x00, 0x0c,
	0x00, 0x00, 0x01, 0x01, 0xcc, 0x00, 0x00, 0x05, 0x01,
	0x00, 0x00, 0x08, 0x0c, 0x11, 0x00, 0x00, 0x0c, 0x0c,
	0x00, 0x00, 0x00, 0x0c, 0x23, 0x00, 0x00, 0x00, 0x0c,
	0x00, 0x00, 0x01, 0x00, 0x04, 0x10, 0x82, 0x00, 0x0c,
	0x00, 0x00, 0x00, 0x0c, 0x56, 0x00, 0x00, 0x00, 0x0c,
	0x00, 0x00, 0x00, 0x0c, 0x77, 0x10, 0x02, 0x00, 0x0c,
	0x00, 0x00, 0x00, 0x0c, 0x88, 0xef, 0xfe, 0x00, 0x0c,
	0x00, 0x00, 0x01, 0x00, 0x09, 0xef, 0x7e, 0x00, 0x0c,
	0x00, 0x00, 0x00, 0x0c, 0xab, 0x00, 0x00, 0x00, 0x0c,
	0x00, 0x00, 0x00, 0x0c, 0xcc, 0xef, 0xfe, 0x00, 0x0c,
	0x00, 0x00, 0x00, 0x0c, 0xdd, 0x10, 0x02, 0x00, 0x0c,
	0x00, 0x00, 0x01, 0x00, 0x0e, 0x08, 0x41, 0x00, 0x0c,
	0x10, 0x01, 0x00, 0x06, 0x99, 0xf0, 0x1f, 0x00, 0x06,
	0x10, 0x00, 0x00, 0x0a, 0xcc, 0xf0, 0x00, 0x00, 0x0a,
	0x00, 0x00, 0x00, 0x0c, 0xf0, 0x08, 0x41, 0x00, 0x0d,
	0x08, 0x02, 0x00, 0x06, 0x99, 0xf8, 0x1e, 0x00, 0x06,
	0x00, 0x02, 0x00, 0x0a, 0xcc, 0xff, 0xfe, 0x00, 0x0a,
	0x00, 0x00, 0x00, 0x0d, 0x12, 0x08, 0x41, 0x00, 0x0d,
	0x00, 0x00, 0x01, 0x00, 0x03, 0xf7, 0xbf, 0x00, 0x0d,
	0xef, 0xff, 0x00, 0x06, 0xee, 0x0f, 0xe1, 0x00, 0x06,
	0xf0, 0x00, 0x00, 0x0b, 0x00, 0x10, 0x00, 0x00, 0x0b,
	0x00, 0x00, 0x00, 0x0d, 0x45, 0xf7, 0xbf, 0x00, 0x0d,
	0xf7, 0xfe, 0x00, 0x06, 0xee, 0x07, 0xe2, 0x00, 0x06,
	0xff, 0xfe, 0x00, 0x0b, 0x00, 0x00, 0x02, 0x00, 0x0b,
	0x00, 0x00, 0x00, 0x0d, 0x67, 0xf7, 0xbf, 0x00, 0x0d,
	0x00, 0x00, 0x00, 0x0d, 0x89, 0x00, 0x00, 0x00, 0x0d,
	0x00, 0x00, 0x01, 0x01, 0x22, 0x00, 0x00, 0x09, 0x01,
	0x00, 0x00, 0x10, 0x0d, 0xaa, 0x00, 0x00, 0x18, 0x0d,
	0x00, 0x00, 0x00, 0x0d, 0xbb, 0x10, 0x82, 0x00, 0x0d,
	0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x20, 0x01, 0x00,
	0x08, 0x41, 0x00, 0x09, 0x44, 0x08, 0x61, 0x00, 0x09,
	0x00, 0x00, 0x00, 0x0a, 0xcc, 0x20, 0x04, 0x00, 0x0d,
	0x00, 0x00, 0x00, 0x0a, 0xcd, 0xdf, 0xfc, 0x00, 0x0d,
	0x00, 0x00, 0x00, 0x0d, 0xee, 0xef, 0x7e, 0x00, 0x0d,
	0x00, 0x00, 0x01, 0x00, 0x00, 0xff, 0xe0, 0x01, 0x00,
	0xf7, 0xbf, 0x00, 0x09, 0x77, 0xf7, 0x9f, 0x00, 0x09,
	0x00, 0x00, 0x00, 0x0b, 0x0f, 0xdf, 0xfc, 0x00, 0x0d,
	0x00, 0x00, 0x00, 0x0b, 0x00, 0x20, 0x04, 0x00, 0x0e,
	0x00, 0x00, 0x01, 0x00, 0x01, 0x08, 0x41, 0x00, 0x0e,
	0x00, 0x00, 0x00, 0x0e, 0x23, 0x00, 0x00, 0x00, 0x0e,
	0x00, 0x00, 0x00, 0x0e, 0x44, 0x08, 0x41, 0x00, 0x0e,
	0x00, 0x00, 0x00, 0x0e, 0x56, 0x00, 0x00, 0x00, 0x0e,
	0x00, 0x00, 0x00, 0x0e, 0x77, 0x08, 0x41, 0x00, 0x0e,
	0x00, 0x00, 0x01, 0x00, 0x08, 0xf7, 0xbf, 0x00, 0x0e,
	0x00, 0x00, 0x00, 0x0e, 0x9a, 0x00, 0x00, 0x00, 0x0e,
	0x00, 0x00, 0x00, 0x0e, 0xbb, 0xf7, 0xbf, 0x00, 0x0e,
	0x00, 0x00, 0x00, 0x0e, 0xcd, 0x00, 0x00, 0x00, 0x0e,
	0x00, 0x00, 0x00, 0x0e, 0xee, 0xf7, 0xbf, 0x00, 0x0e,
	0x00, 0x00, 0x01, 0x01, 0xcc, 0x00, 0x00, 0x09, 0x01,
	0x00, 0x00, 0x10, 0x0e, 0xff, 0x00, 0x00, 0x18, 0x0e,
	0x00, 0x00, 0x00, 0x0f, 0x01, 0x00, 0x00, 0x00, 0x0f,
	0x00, 0x00, 0x01, 0x00, 0x02, 0x21, 0x04, 0x00, 0x0f,
	0x00, 0x00, 0x00, 0x0a, 0xc3, 0x00, 0x00, 0x00, 0x0f,
	0x00, 0x00, 0x00, 0x0a, 0xc4, 0x00, 0x00, 0x00, 0x0f,
	0x00, 0x00, 0x01, 0x00, 0x05, 0xde, 0xfc, 0x00, 0x0f,
	0x00, 0x00, 0x00, 0x0b, 0x06, 0x00, 0x00, 0x00, 0x0f,
	0x00, 0x00, 0x00, 0x0b, 0x07, 0x00, 0x00, 0x00, 0x0f,
	0x00, 0x00, 0x01, 0x00, 0x08, 0x08, 0x41, 0x00, 0x0f,
	0x08, 0x00, 0x00, 0x0f, 0x9a, 0x0f, 0xff, 0x00, 0x0f,
	0xf8, 0x00, 0x00, 0x0f, 0xbc, 0xf0, 0x01, 0x00, 0x0f,
	0x00, 0x00, 0x00, 0x0c, 0xfd, 0x10, 0x82, 0x00, 0x0f,
	0x00, 0x01, 0x00, 0x0f, 0xec, 0xf8, 0x02, 0x00, 0x0f,
	0xff, 0xff, 0x00, 0x0f, 0xfa, 0x07, 0xfe, 0x00, 0x0f,
	0x00, 0x00, 0x00, 0x0d, 0x10, 0x10, 0x82, 0x00, 0x10,
	0x00, 0x00, 0x01, 0x00, 0x01, 0xf7, 0xbf, 0x00, 0x10,
	0xf8, 0x00, 0x00, 0x0f, 0xb2, 0xf0, 0x01, 0x00, 0x10,
	0x08, 0x00, 0x00, 0x0f, 0x93, 0x0f, 0xff, 0x00, 0x10,
	0x00, 0x00, 0x00, 0x0d, 0x44, 0xef, 0x7e, 0x00, 0x10,
	0xff, 0xff, 0x00, 0x0f, 0xf3, 0x07, 0xfe, 0x00, 0x10,
	0x00, 0x01, 0x00, 0x0f, 0xe2, 0xf8, 0x02, 0x00, 0x10,
	0x00, 0x00, 0x00, 0x0d, 0x65, 0xef, 0x7e, 0x00, 0x10,
	0x00, 0x00, 0x00, 0x10, 0x67, 0x00, 0x00, 0x00, 0x10,
	0x00, 0x00, 0x01, 0x01, 0x22, 0x00, 0x00, 0x11, 0x01,
	0x00, 0x00, 0x20, 0x10, 0x88, 0x00, 0x00, 0x30, 0x10,
	0x00, 0x00, 0x01, 0x00, 0x09, 0x00, 0x00, 0x00, 0x10,
	0x20, 0x04, 0x00, 0x0a, 0xcc, 0x40, 0x08, 0x00, 0x0a,
	0xdf, 0xfc, 0x00, 0x0a, 0xcc, 0xbf, 0xf8, 0x00, 0x0a,
	0x00, 0x00, 0x01, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x10,
	0xdf, 0xfc, 0x00, 0x0b, 0x00, 0xbf, 0xf8, 0x00, 0x0b,
	0x20, 0x04, 0x00, 0x0b, 0x00, 0x40, 0x08, 0x00, 0x0b,
	0x00, 0x00, 0x01, 0x00, 0x0b, 0x08, 0x41, 0x00, 0x10,
	0x00, 0x00, 0x00, 0x10, 0xcc, 0x08, 0x01, 0x00, 0x10,
	0x00, 0x00, 0x00, 0x10, 0xdd, 0x08, 0x00, 0x00, 0x10,
	0x00, 0x00, 0x00, 0x10, 0xee, 0xf7, 0xff, 0x00, 0x10,
	0x00, 0x00, 0x00, 0x10, 0xff, 0x00, 0x01, 0x00, 0x10,
	0x00, 0x00, 0x00, 0x11, 0x00, 0x10, 0x82, 0x00, 0x11,
	0x00, 0x00, 0x00, 0x11, 0x11, 0x08, 0x01, 0x00, 0x11,
	0x00, 0x00, 0x00, 0x11, 0x22, 0xf7, 0xff, 0x00, 0x11,
	0x00, 0x00, 0x00, 0x11, 0x33, 0x10, 0x82, 0x00, 0x11,
	0x00, 0x00, 0x01, 0x00, 0x04, 0xf7, 0xbf, 0x00, 0x11,
	0x00, 0x00, 0x00, 0x11, 0x55, 0xf8, 0x00, 0x00, 0x11,
	0x00, 0x00, 0x00, 0x11, 0x66, 0xff, 0xff, 0x00, 0x11,
	0x00, 0x00, 0x00, 0x11, 0x77, 0xef, 0x7e, 0x00, 0x11,
	0x00, 0x00, 0x00, 0x11, 0x88, 0xef, 0x7e, 0x00, 0x11,
	0x00, 0x00, 0x01, 0x01, 0xcc, 0x00, 0x00, 0x11, 0x01,
	0x00, 0x00, 0x20, 0x11, 0x99, 0x00, 0x00, 0x30, 0x11,
	0x00, 0x00, 0x00, 0x11, 0xab, 0x00, 0x00, 0x00, 0x11,
	0x21, 0x04, 0x01, 0x00, 0x00, 0x42, 0x08, 0x01, 0x00,
	0xde, 0xfc, 0x01, 0x00, 0x00, 0xbd, 0xf8, 0x01, 0x00,
	0x00, 0x00, 0x01, 0x00, 0x0c, 0x08, 0x41, 0x00, 0x11,
	0x00, 0x00, 0x00, 0x11, 0xde, 0x10, 0x02, 0x00, 0x11,
	0x00, 0x00, 0x00, 0x11, 0xf0, 0x10, 0x00, 0x00, 0x12,
	0x00, 0x00, 0x00, 0x12, 0x12, 0xef, 0xfe, 0x00, 0x12,
	0x00, 0x00, 0x00, 0x12, 0x13, 0x00, 0x02, 0x00, 0x12,
	0x00, 0x00, 0x00, 0x0c, 0xf4, 0x21, 0x04, 0x00, 0x12,
	0x00, 0x00, 0x00, 0x12, 0x56, 0x10, 0x02, 0x00, 0x12,
	0x00, 0x00, 0x00, 0x11, 0xf7, 0xef, 0xfe, 0x00, 0x12,
	0x00, 0x00, 0x00, 0x0d, 0x18, 0x21, 0x04, 0x00, 0x12,
	0x00, 0x00, 0x01, 0x00, 0x09, 0xf7, 0xbf, 0x00, 0x12,
	0x00, 0x00, 0x00, 0x12, 0x5a, 0xf0, 0x00, 0x00, 0x12,
	0x00, 0x00, 0x00, 0x11, 0xdb, 0xff, 0xfe, 0x00, 0x12,
	0x00, 0x00, 0x00, 0x0d, 0x4c, 0xde, 0xfc, 0x00, 0x12,
	0x00, 0x00, 0x00, 0x0d, 0x6d, 0xde, 0xfc, 0x00, 0x12,
	0x00, 0x00, 0x00, 0x12, 0xef, 0x00, 0x00, 0x00, 0x12,
	0x00, 0x00, 0x01, 0x01, 0x22, 0x00, 0x00, 0x21, 0x01,
	0x00, 0x00, 0x40, 0x13, 0x00, 0x00, 0x00, 0x60, 0x13,
	0x00, 0x00, 0x01, 0x00, 0x01, 0x08, 0x41, 0x00, 0x13,
	0x00, 0x00, 0x00, 0x13, 0x22, 0x08, 0x00, 0x00, 0x13,
	0x00, 0x00, 0x00, 0x13, 0x33, 0x10, 0x02, 0x00, 0x13,
	0x00, 0x00, 0x00, 0x13, 0x44, 0xff, 0xff, 0x00, 0x13,
	0x00, 0x00, 0x00, 0x13, 0x55, 0x10, 0x00, 0x00, 0x13,
	0x00, 0x00, 0x00, 0x13, 0x66, 0xf8, 0x00, 0x00, 0x13,
	0x00, 0x00, 0x00, 0x13, 0x77, 0xef, 0xfe, 0x00, 0x13,
	0x00, 0x00, 0x00, 0x13, 0x88, 0x00, 0x02, 0x00, 0x13,
	0x00, 0x00, 0x00, 0x13, 0x99, 0x21, 0x04, 0x00, 0x13,
	0x00, 0x00, 0x00, 0x13, 0xaa, 0x00, 0x01, 0x00, 0x13,
	0x00, 0x00, 0x00, 0x13, 0xbb, 0x10, 0x02, 0x00, 0x13,
	0x00, 0x00, 0x00, 0x13, 0xcc, 0xef, 0xfe, 0x00, 0x13,
	0x00, 0x00, 0x00, 0x13, 0xdd, 0x21, 0x04, 0x00, 0x13,
	0x00, 0x00, 0x01, 0x00, 0x0e, 0xf7, 0xbf, 0x00, 0x13,
	0x00, 0x00, 0x00, 0x13, 0xff, 0xf0, 0x00, 0x00, 0x13,
	0x00, 0x00, 0x00, 0x14, 0x00, 0xff, 0xfe, 0x00, 0x14,
	0x00, 0x00, 0x00, 0x14, 0x11, 0xde, 0xfc, 0x00, 0x14,
	0x00, 0x00, 0x00, 0x14, 0x22, 0xde, 0xfc, 0x00, 0x14,
	0x00, 0x00, 0x01, 0x01, 0xcc, 0x00, 0x00, 0x21, 0x01,
	0x00, 0x00, 0x40, 0x14, 0x33, 0x00, 0x00, 0x60, 0x14,
	0x00, 0x00, 0x01, 0x01, 0x22, 0x00, 0x00, 0x41, 0x01,
	0x00, 0x00, 0x01, 0x00, 0x04, 0x08, 0x41, 0x00, 0x14,
	0x00, 0x00, 0x01, 0x00, 0x05, 0x10, 0x00, 0x00, 0x14,
	0x00, 0x00, 0x00, 0x11, 0xd6, 0x20, 0x04, 0x00, 0x14,
	0x00, 0x00, 0x01, 0x00, 0x07, 0xff, 0xfe, 0x00, 0x14,
	0x00, 0x00, 0x00, 0x11, 0xf8, 0x20, 0x00, 0x00, 0x14,
	0x00, 0x00, 0x01, 0x00, 0x09, 0xf0, 0x00, 0x00, 0x14,
	0x00, 0x00, 0x00, 0x12, 0x1a, 0xdf, 0xfc, 0x00, 0x14,
	0x00, 0x00, 0x00, 0x12, 0x1b, 0x00, 0x04, 0x00, 0x14,
	0x00, 0x00, 0x00, 0x0c, 0xfc, 0x42, 0x08, 0x00, 0x14,
	0x00, 0x00, 0x01, 0x00, 0x0d, 0x00, 0x02, 0x00, 0x14,
	0x00, 0x00, 0x00, 0x12, 0x5e, 0x20, 0x04, 0x00, 0x14,
	0x00, 0x00, 0x00, 0x11, 0xff, 0xdf, 0xfc, 0x00, 0x14,
	0x00, 0x00, 0x00, 0x0d, 0x10, 0x42, 0x08, 0x00, 0x15,
	0x00, 0x00, 0x01, 0x00, 0x01, 0xf7, 0xbf, 0x00, 0x15,
	0x00, 0x00, 0x00, 0x12, 0x52, 0xe0, 0x00, 0x00, 0x15,
	0x00, 0x00, 0x00, 0x11, 0xd3, 0xff, 0xfc, 0x00, 0x15,
	0x00, 0x00, 0x00, 0x0d, 0x44, 0xbd, 0xf8, 0x00, 0x15,
	0x00, 0x00, 0x00, 0x0d, 0x65, 0xbd, 0xf8, 0x00, 0x15,
	0x00, 0x00, 0x01, 0x01, 0xcc, 0x00, 0x00, 0x41, 0x01,
	0x00, 0x00, 0x01, 0x00, 0x06, 0x08, 0x41, 0x00, 0x15,
	0x00, 0x00, 0x00, 0x15, 0x77, 0x10, 0x00, 0x00, 0x15,
	0x00, 0x00, 0x00, 0x11, 0xd8, 0x00, 0x00, 0x00, 0x15,
	0x00, 0x00, 0x00, 0x15, 0x99, 0xff, 0xfe, 0x00, 0x15,
	0x00, 0x00, 0x00, 0x11, 0xfa, 0x00, 0x00, 0x00, 0x15,
	0x00, 0x00, 0x00, 0x15, 0xbb, 0xf0, 0x00, 0x00, 0x15,
	0x00, 0x00, 0x00, 0x12, 0x1c, 0x00, 0x00, 0x00, 0x15,
	0x00, 0x00, 0x00, 0x12, 0x1d, 0x00, 0x00, 0x00, 0x15,
	0x00, 0x00, 0x00, 0x0c, 0xfe, 0x00, 0x00, 0x00, 0x15,
	0x00, 0x00, 0x00, 0x15, 0xff, 0x00, 0x02, 0x00, 0x15,
	0x00, 0x00, 0x00, 0x12, 0x50, 0x00, 0x00, 0x00, 0x16,
	0x00, 0x00, 0x00, 0x11, 0xf1, 0x00, 0x00, 0x00, 0x16,
	0x00, 0x00, 0x00, 0x0d, 0x12, 0x00, 0x00, 0x00, 0x16,
	0x00, 0x00, 0x01, 0x00, 0x03, 0xf7, 0xbf, 0x00, 0x16,
	0x00, 0x00, 0x00, 0x12, 0x54, 0x00, 0x00, 0x00, 0x16,
	0x00, 0x00, 0x00, 0x11, 0xd5, 0x00, 0x00, 0x00, 0x16,
	0x00, 0x00, 0x00, 0x0d, 0x46, 0x00, 0x00, 0x00, 0x16,
	0x00, 0x00, 0x00, 0x0d, 0x67, 0x00, 0x00, 0x00, 0x16,
	0x00, 0x00, 0x01, 0x00, 0x08, 0x08, 0x41, 0x00, 0x16,
	0x00, 0x00, 0x01, 0x00, 0x09, 0x20, 0x00, 0x00, 0x16,
	0x20, 0x04, 0x00, 0x11, 0xdd, 0x40, 0x08, 0x00, 0x11,
	0x00, 0x00, 0x01, 0x00, 0x0a, 0xff, 0xfc, 0x00, 0x16,
	0x20, 0x00, 0x00, 0x11, 0xff, 0x40, 0x00, 0x00, 0x11,
	0x00, 0x00, 0x01, 0x00, 0x0b, 0xe0, 0x00, 0x00, 0x16,
	0xdf, 0xfc, 0x00, 0x12, 0x11, 0xbf, 0xf8, 0x00, 0x12,
	0x00, 0x04, 0x00, 0x12, 0x11, 0x00, 0x08, 0x00, 0x12,
	0x42, 0x08, 0x00, 0x0c, 0xff, 0x83, 0xf0, 0x00, 0x0c,
	0x00, 0x00, 0x01, 0x00, 0x0c, 0x00, 0x04, 0x00, 0x16,
	0x20, 0x04, 0x00, 0x12, 0x55, 0x40, 0x08, 0x00, 0x12,
	0xdf, 0xfc, 0x00, 0x11, 0xff, 0xbf, 0xf8, 0x00, 0x11,
	0x42, 0x08, 0x00, 0x0d, 0x11, 0x83, 0xf1, 0x00, 0x0d,
	0x00, 0x00, 0x01, 0x00, 0x0d, 0xf7, 0xbf, 0x00, 0x16,
	0xe0, 0x00, 0x00, 0x12, 0x55, 0xc0, 0x00, 0x00, 0x12,
	0xff, 0xfc, 0x00, 0x11, 0xdd, 0xff, 0xf8, 0x00, 0x11,
	0xbd, 0xf8, 0x00, 0x0d, 0x44, 0x7b, 0xf0, 0x00, 0x0d,
	0xbd, 0xf8, 0x00, 0x0d, 0x66, 0x74, 0x0f, 0x00, 0x0d,
	0x00, 0x00, 0x01, 0x00, 0x0e, 0x08, 0x41, 0x00, 0x16,
	0x00, 0x00, 0x01, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x16,
	0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x17,
	0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x17,
	0x00, 0x00, 0x01, 0x00, 0x02, 0x00, 0x00, 0x00, 0x17,
	0x00, 0x00, 0x01, 0x00, 0x03, 0xf7, 0xbf, 0x00, 0x17,
	0x00, 0x00, 0x01, 0x00, 0x04, 0x08, 0x41, 0x00, 0x17,
	0x20, 0x00, 0x01, 0x00, 0x00, 0x40, 0x00, 0x01, 0x00,
	0xff, 0xfc, 0x01, 0x00, 0x00, 0xff, 0xf8, 0x01, 0x00,
	0xe0, 0x00, 0x01, 0x00, 0x00, 0xc0, 0x00, 0x01, 0x00,
	0x00, 0x04, 0x01, 0x00, 0x00, 0x00, 0x08, 0x01, 0x00,
	0x00, 0x00, 0x01, 0x00, 0x05, 0xf7, 0xbf, 0x00, 0x17,
	0x00, 0x00, 0x01, 0x00, 0x06, 0x08, 0x41, 0x00, 0x17,
	0x00, 0x00, 0x01, 0x00, 0x07, 0xf7, 0xbf, 0x00, 0x17,
	0x00, 0x00, 0x01, 0x00, 0x00, 0x08, 0x41, 0x01, 0x00,
	0x00, 0x00, 0x01, 0x00, 0x00, 0xf7, 0xbf, 0x01, 0x00,
	0xff, 0xff, 0xff, 0x7f, 0xff, 0xff, 0xff, 0xff, 0x7f,
	0xff, 0xff, 0xff, 0x7f, 0xff, 0xff, 0xff, 0xff, 0x7f,
	0xff, 0xff, 0xff, 0x7f, 0xff, 0xff, 0xff, 0xff, 0x7f,
	0xff, 0xff, 0xff, 0x7f, 0xff, 0xff, 0xff, 0xff, 0x7f,
	0xff, 0xff, 0xff, 0x7f, 0xff, 0xff, 0xff, 0xff, 0x7f,
	0xff, 0xff, 0xff, 0x7f, 0xff, 0xff, 0xff, 0xff, 0x7f,
	0xff, 0xff, 0xff, 0x7f, 0xff, 0xff, 0xff, 0xff, 0x7f,
	0xff, 0xff, 0xff, 0x7f, 0xff, 0xff, 0xff, 0xff, 0x7f,
	0xff, 0xff, 0xff, 0x7f, 0xff, 0xff, 0xff, 0xff, 0x7f,
	0xff, 0xff, 0xff, 0x7f, 0xff, 0xff, 0xff, 0xff, 0x7f,
	0xff, 0xff, 0xff, 0x7f, 0xff, 0xff, 0xff, 0xff, 0x7f,
	0xff, 0xff, 0xff, 0x7f, 0xff, 0xff, 0xff, 0xff, 0x7f,
	0xff, 0xff, 0xff, 0x7f, 0xff, 0xff, 0xff, 0xff, 0x7f,
	0xff, 0xff, 0xff, 0x7f, 0xff, 0xff, 0xff, 0xff, 0x7f,
	0xff, 0xff, 0xff, 0x7f, 0xff, 0xff, 0xff, 0xff, 0x7f,
	0xff, 0xff, 0xff, 0x7f, 0xff, 0xff, 0xff, 0xff, 0x7f,
	0xff, 0xff, 0xff, 0x7f, 0xff, 0xff, 0xff, 0xff, 0x7f,
	0xff, 0xff, 0xff, 0x7f, 0xff, 0xff, 0xff, 0xff, 0x7f,
	0xff, 0xff, 0xff, 0x7f, 0xff, 0xff, 0xff, 0xff, 0x7f,
	0xff, 0xff, 0xff, 0x7f, 0xff, 0xff, 0xff, 0xff, 0x7f,
	0xff, 0xff, 0xff, 0x7f, 0xff, 0xff, 0xff, 0xff, 0x7f,
	0xff, 0xff, 0xff, 0x7f, 0xff, 0xff, 0xff, 0xff, 0x7f,
	0xff, 0xff, 0xff, 0x7f, 0xff, 0xff, 0xff, 0xff, 0x7f,
	0xff, 0xff, 0xff, 0x7f, 0xff, 0xff, 0xff, 0xff, 0x7f,
	0xff, 0xff, 0xff, 0x7f, 0xff, 0xff, 0xff, 0xff, 0x7f,
	0xff, 0xff, 0xff, 0x7f, 0xff, 0xff, 0xff, 0xff, 0x7f,
	0xff, 0xff, 0xff, 0x7f, 0xff, 0xff, 0xff, 0xff, 0x7f,
	0xff, 0xff, 0xff, 0x7f, 0xff, 0xff, 0xff, 0xff, 0x7f,
	0xff, 0xff, 0xff, 0x7f, 0xff, 0xff, 0xff, 0xff, 0x7f,
	0xff, 0xff, 0xff, 0x7f, 0xff, 0xff, 0xff, 0xff, 0x7f,
	0xff, 0xff, 0xff, 0x7f, 0xff, 0xff, 0xff, 0xff, 0x7f,
	0xff, 0xff, 0xff, 0x7f, 0xff, 0xff, 0xff, 0xff, 0x7f,
	0xff, 0xff, 0xff, 0x7f, 0xff, 0xff, 0xff, 0xff, 0x7f,
	0xff, 0xff, 0xff, 0x7f, 0xff, 0xff, 0xff, 0xff, 0x7f,
	0xff, 0xff, 0xff, 0x7f, 0xff, 0xff, 0xff, 0xff, 0x7f,
	0xff, 0xff, 0xff, 0x7f, 0xff, 0xff, 0xff, 0xff, 0x7f,
	0xff, 0xff, 0xff, 0x7f, 0xff, 0xff, 0xff, 0xff, 0x7f,
	0xff, 0xff, 0xff, 0x7f, 0xff, 0xff, 0xff, 0xff, 0x7f,
	0xff, 0xff, 0xff, 0x7f, 0xff, 0xff, 0xff, 0xff, 0x7f,
	0xff, 0xff, 0xff, 0x7f, 0xff, 0xff, 0xff, 0xff, 0x7f,
	0xff, 0xff, 0xff, 0x7f, 0xff, 0xff, 0xff, 0xff, 0x7f,
	0xff, 0xff, 0xff, 0x7f, 0xff, 0xff, 0xff, 0xff, 0x7f,
	0xff, 0xff, 0xff, 0x7f, 0xff, 0xff, 0xff, 0xff, 0x7f,
	0xff, 0xff, 0xff, 0x7f, 0xff, 0xff, 0xff, 0xff, 0x7f,
	0xff, 0xff, 0xff, 0x7f, 0xff, 0xff, 0xff, 0xff, 0x7f,
	0xff, 0xff, 0xff, 0x7f, 0xff, 0xff, 0xff, 0xff, 0x7f,
	0xff, 0xff, 0xff, 0x7f, 0xff, 0xff, 0xff, 0xff, 0x7f,
	0xff, 0xff, 0xff, 0x7f, 0xff, 0xff, 0xff, 0xff, 0x7f,
	0xff, 0xff, 0xff, 0x7f, 0xff, 0xff, 0xff, 0xff, 0x7f,
	0xff, 0xff, 0xff, 0x7f, 0xff, 0xff, 0xff, 0xff, 0x7f,
	0xff, 0xff, 0xff, 0x7f, 0xff, 0xff, 0xff, 0xff, 0x7f,
	0xff, 0xff, 0xff, 0x7f, 0xff, 0xff, 0xff, 0xff, 0x7f,
	0xff, 0xff, 0xff, 0x7f, 0xff, 0xff, 0xff, 0xff, 0x7f,
	0xff, 0xff, 0xff, 0x7f, 0xff, 0xff, 0xff, 0xff, 0x7f,
	0xff, 0xff, 0xff, 0x7f, 0xff, 0xff, 0xff, 0xff, 0x7f,
	0xff, 0xff, 0xff, 0x7f, 0xff, 0xff, 0xff, 0xff, 0x7f,
	0xff, 0xff, 0xff, 0x7f, 0xff, 0xff, 0xff, 0xff, 0x7f,
	0xff, 0xff, 0xff, 0x7f, 0xff, 0xff, 0xff, 0xff, 0x7f,
	0xff, 0xff, 0xff, 0x7f, 0xff, 0xff, 0xff, 0xff, 0x7f,
	0xff, 0xff, 0xff, 0x7f, 0xff, 0xff, 0xff, 0xff, 0x7f,
	0xff, 0xff, 0xff, 0x7f, 0xff, 0xff, 0xff, 0xff, 0x7f,
	0xff, 0xff, 0xff, 0x7f, 0xff, 0xff, 0xff, 0xff, 0x7f,
	0xff, 0xff, 0xff, 0x7f, 0xff, 0xff, 0xff, 0xff, 0x7f,
	0xff, 0xff, 0xff, 0x7f, 0xff, 0xff, 0xff, 0xff, 0x7f,
	0xff, 0xff, 0xff, 0x7f, 0xff, 0xff, 0xff, 0xff, 0x7f,
	0xff, 0xff, 0xff, 0x7f, 0xff, 0xff, 0xff, 0xff, 0x7f,
	0xff, 0xff, 0xff, 0x7f, 0xff, 0xff, 0xff, 0xff, 0x7f,
	0xff, 0xff, 0xff, 0x7f, 0xff, 0xff, 0xff, 0xff, 0x7f,
	0xff, 0xff, 0xff, 0x7f, 0xff, 0xff, 0xff, 0xff, 0x7f,
	0xff, 0xff, 0xff, 0x7f, 0xff, 0xff, 0xff, 0xff, 0x7f,
	0xff, 0xff, 0xff, 0x7f, 0xff, 0xff, 0xff, 0xff, 0x7f,
	0xff, 0xff, 0xff, 0x7f, 0xff, 0xff, 0xff, 0xff, 0x7f,
	0xff, 0xff, 0xff, 0x7f, 0xff, 0xff, 0xff, 0xff, 0x7f,
	0xff, 0xff, 0xff, 0x7f, 0xff, 0xff, 0xff, 0xff, 0x7f,
	0xff, 0xff, 0xff, 0x7f, 0xff, 0xff, 0xff, 0xff, 0x7f,
	0xff, 0xff, 0xff, 0x7f, 0xff, 0xff, 0xff, 0xff, 0x7f,
	0xff, 0xff, 0xff, 0x7f, 0xff, 0xff, 0xff, 0xff, 0x7f,
	0xff, 0xff, 0xff, 0x7f, 0xff, 0xff, 0xff, 0xff, 0x7f,
	0xff, 0xff, 0xff, 0x7f, 0xff, 0xff, 0xff, 0xff, 0x7f,
	0xff, 0xff, 0xff, 0x7f, 0xff, 0xff, 0xff, 0xff, 0x7f,
	0xff, 0xff, 0xff, 0x7f, 0xff, 0xff, 0xff, 0xff, 0x7f,
	0xff, 0xff, 0xff, 0x7f, 0xff, 0xff, 0xff, 0xff, 0x7f,
	0xff, 0xff, 0xff, 0x7f, 0xff, 0xff, 0xff, 0xff, 0x7f,
	0xff, 0xff, 0xff, 0x7f, 0xff, 0xff, 0xff, 0xff, 0x7f,
	0xff, 0xff, 0xff, 0x7f, 0xff, 0xff, 0xff, 0xff, 0x7f,
	0xff, 0xff, 0xff, 0x7f, 0xff, 0xff, 0xff, 0xff, 0x7f,
	0xff, 0xff, 0xff, 0x7f, 0xff, 0xff, 0xff, 0xff, 0x7f,
	0xff, 0xff, 0xff, 0x7f, 0xff, 0xff, 0xff, 0xff, 0x7f,
	0xff, 0xff, 0xff, 0x7f, 0xff, 0xff, 0xff, 0xff, 0x7f,
	0xff, 0xff, 0xff, 0x7f, 0xff, 0xff, 0xff, 0xff, 0x7f,
	0xff, 0xff, 0xff, 0x7f, 0xff, 0xff, 0xff, 0xff, 0x7f,
	0xff, 0xff, 0xff, 0x7f, 0xff, 0xff, 0xff, 0xff, 0x7f,
	0xff, 0xff, 0xff, 0x7f, 0xff, 0xff, 0xff, 0xff, 0x7f,
	0xff, 0xff, 0xff, 0x7f, 0xff, 0xff, 0xff, 0xff, 0x7f,
	0xff, 0xff, 0xff, 0x7f, 0xff, 0xff, 0xff, 0xff, 0x7f,
	0xff, 0xff, 0xff, 0x7f, 0xff, 0xff, 0xff, 0xff, 0x7f,
	0xff, 0xff, 0xff, 0x7f, 0xff, 0xff, 0xff, 0xff, 0x7f,
	0xff, 0xff, 0xff, 0x7f, 0xff, 0xff, 0xff, 0xff, 0x7f,
	0xff, 0xff, 0xff, 0x7f, 0xff, 0xff, 0xff, 0xff, 0x7f,
	0xff, 0xff, 0xff, 0x7f, 0xff, 0xff, 0xff, 0xff, 0x7f,
	0xff, 0xff, 0xff, 0x7f, 0xff, 0xff, 0xff, 0xff, 0x7f,
	0xff, 0xff, 0xff, 0x7f, 0xff, 0xff, 0xff, 0xff, 0x7f,
	0xff, 0xff, 0xff, 0x7f, 0xff, 0xff, 0xff, 0xff, 0x7f,
	0xff, 0xff, 0xff, 0x7f, 0xff, 0xff, 0xff, 0xff, 0x7f,
	0xff, 0xff, 0xff, 0x7f, 0xff, 0xff, 0xff, 0xff, 0x7f,
	0xff, 0xff, 0xff, 0x7f, 0xff, 0xff, 0xff, 0xff, 0x7f,
	0xff, 0xff, 0xff, 0x7f, 0xff, 0xff, 0xff, 0xff, 0x7f,
	0xff, 0xff, 0xff, 0x7f, 0xff, 0xff, 0xff, 0xff, 0x7f,
	0xff, 0xff, 0xff, 0x7f, 0xff, 0xff, 0xff, 0xff, 0x7f,
	0xff, 0xff, 0xff, 0x7f, 0xff, 0xff, 0xff, 0xff, 0x7f,
	0xff, 0xff, 0xff, 0x7f, 0xff, 0xff, 0xff, 0xff, 0x7f,
	0xff, 0xff, 0xff, 0x7f, 0xff, 0xff, 0xff, 0xff, 0x7f,
	0xff, 0xff, 0xff, 0x7f, 0xff, 0xff, 0xff, 0xff, 0x7f,
	0xff, 0xff, 0xff, 0x7f, 0xff, 0xff, 0xff, 0xff, 0x7f,
	0xff, 0xff, 0xff, 0x7f, 0xff, 0xff, 0xff, 0xff, 0x7f,
	0xff, 0xff, 0xff, 0x7f, 0xff, 0xff, 0xff, 0xff, 0x7f,
	0xff, 0xff, 0xff, 0x7f, 0xff, 0xff, 0xff, 0xff, 0x7f,
	0xff, 0xff, 0xff, 0x7f, 0xff, 0xff, 0xff, 0xff, 0x7f,
	0xff, 0xff, 0xff, 0x7f, 0xff, 0xff, 0xff, 0xff, 0x7f,
	0xff, 0xff, 0xff, 0x7f, 0xff, 0xff, 0xff, 0xff, 0x7f,
	0xff, 0xff, 0xff, 0x7f, 0xff, 0xff, 0xff, 0xff, 0x7f,
	0xff, 0xff, 0xff, 0x7f, 0xff, 0xff, 0xff, 0xff, 0x7f,
	0xff, 0xff, 0xff, 0x7f, 0xff, 0xff, 0xff, 0xff, 0x7f,
	0xff, 0xff, 0xff, 0x7f, 0xff, 0xff, 0xff, 0xff, 0x7f,
	0xff, 0xff, 0xff, 0x7f, 0xff, 0xff, 0xff, 0xff, 0x7f,
	0xff, 0xff, 0xff, 0x7f, 0xff, 0xff, 0xff, 0xff, 0x7f,
	0xff, 0xff, 0xff, 0x7f, 0xff, 0xff, 0xff, 0xff, 0x7f,
	0xff, 0xff, 0xff, 0x7f, 0xff, 0xff, 0xff, 0xff, 0x7f,
	0xff, 0xff, 0xff, 0x7f, 0xff, 0xff, 0xff, 0xff, 0x7f,
	0xff, 0xff, 0xff, 0x7f, 0xff, 0xff, 0xff, 0xff, 0x7f,
	0xff, 0xff, 0xff, 0x7f, 0xff, 0xff, 0xff, 0xff, 0x7f,
	0xff, 0xff, 0xff, 0x7f, 0xff, 0xff, 0xff, 0xff, 0x7f,
	0xff, 0xff, 0xff, 0x7f, 0xff, 0xff, 0xff, 0xff, 0x7f,
	0xff, 0xff, 0xff, 0x7f, 0xff, 0xff, 0xff, 0xff, 0x7f,
	0xff, 0xff, 0xff, 0x7f, 0xff, 0xff, 0xff, 0xff, 0x7f,
	0xff, 0xff, 0xff, 0x7f, 0xff, 0xff, 0xff, 0xff, 0x7f
};

void dl_init( usb_dev_handle* handle ) {

	uint8_t edid[128];
	uint8_t peek;

	dl_cmdstream cs;
	create( &cs, 10*1024 );

	printf("dl_init(): starting DisplayLink initialization..\n");

	// windows driver does this about once a second:
	// f0005000 seems to be default response
	// f0002000 sometimes seen when device is messed up
	int poll = dl_poll( handle );
	printf( "  dl_poll() = 0x%08x\n", poll );

	// always seems to return 0x82
	peek = dl_peek( 0xC484, handle );
	printf( "  dl_peek(0xC484) = 0x%02hhx\n", peek );

	// original driver does this, but no visible effect
	printf( "  dl_poke(0xC41F,0x01)\n" );
	dl_poke( 0xC41F, 0x01, handle );

	dl_get_edid( edid, handle );
	printf( "  EDID data:\n" );
	for (int i = 0; i < 8; i++) {
		printf( "    " );
		for (int j = 0; j < 16; j++) printf( "%02hhx ", edid[i*16+j] );
		printf( "\n" );
	}

	printf( "  setting decryption null-key..\n" );
	dl_set_key( nullkey1, handle );

	// original driver does this, but no visible effect
	printf( "  dl_poke(0xC40B,0x00)\n" );
	dl_poke( 0xC40B, 0x00, handle );
	
	printf( "  sending decompressor table (%d bytes)..\n", sizeof(dl_decomp_table) );
	dl_decomp_table_command( &cs, sizeof(dl_decomp_table), dl_decomp_table );
	send( &cs, handle );

	printf("dl_init(): initialization done.\n\n");
	destroy( &cs );
}

void dl_dumpmem( usb_dev_handle* handle, char* f ) {
	FILE* dump = fopen(f,"w+");
	for (int base = 0; base < 0x100; base++) {
		fprintf(dump,"  register space @ 0x%04x:\n", base<<8 );
		for (int i = 0; i < 256; i++ ) {
			if (i % 16 == 0) fprintf(dump,"    ");
			uint8_t peek = dl_peek( (base<<8)+i, handle );
			fprintf(dump,"%02hhx ",peek);
			if (i % 16 == 15) fprintf(dump,"\n");
		}
	}
	fclose(dump);
}

/******************* HELPER FUNCTIONS *********************/

usb_dev_handle* usb_get_device_handle( int vendor, int product, int interface = 0 ) {

	usb_init();
	usb_find_busses();
	usb_find_devices();

	struct usb_bus* busses = usb_get_busses();
		
	for ( struct usb_bus* bus = busses; bus; bus = bus->next ) {
		for ( struct usb_device* dev = bus->devices; dev; dev = dev->next ) {
			if ((dev->descriptor.idVendor == vendor) && (dev->descriptor.idProduct == product)) {
				usb_dev_handle* handle = usb_open(dev);
				if (!handle) return 0;
				if (usb_claim_interface(handle,0) < 0) return 0;
				return handle;
			}
		}
	}
	return 0;
}

void rgb24_to_rgb16( uint8_t* rgb24, uint8_t* rgb16, int count ) {
	for (int i = 0; i < count; i++) {
		uint8_t r = rgb24[i*3+0];
		uint8_t g = rgb24[i*3+1];
		uint8_t b = rgb24[i*3+2];
		rgb16[i*2+0] =  (r & 0xF8)       | ((g & 0xE0) >> 5);
		rgb16[i*2+1] = ((g & 0x1C) << 3) | ((b & 0xF8) >> 3);
	}
}


void read_rgb24( const char* filename, uint8_t* rgb24, int count ) {
	int f = open(filename,O_RDONLY);
	read( f, rgb24, count*3 );
	close(f);
}

uint8_t* read_rgb16( const char* filename, int count ) {

	uint8_t* rgb16 = (uint8_t*)malloc(count*2);
	uint8_t* rgb24 = (uint8_t*)malloc(count*3);

	read_rgb24(filename,rgb24,count);
	rgb24_to_rgb16(rgb24,rgb16,count);

	free( rgb24 );
	return rgb16;
}


/******************* MAIN ROUTINE *************************/

int main(int argc, char* argv[] ) {

	printf("\ndisplaylink userspace controller demo 0.0.1\n\n");
	printf("written 2008/09 by floe at butterbrot.org\n");
	printf("in cooperation with chrisly at platon42.de\n");
 	printf("this code is released as public domain.\n\n");
	printf("this is so experimental that the warranty shot itself.\n");
	printf("so don't expect any.\n\n");
	printf("(note: you can pass a 640x960 pixel RGB raw image file as parameter)\n\n");

	#define XRES 640
	#define YRES 480

	dl_cmdstream cs;
	create( &cs, 1024*1024 );

	usb_dev_handle* handle = usb_get_device_handle( 0x17E9, 0x01AE );
	if (!handle) return 1;

	// startup control messages & firmware
	dl_init( handle );

	// default register set & offsets
	printf("setting default registers for 640x480@60Hz..\n");
	dl_set_registers( &cs, dl_register_init_640x480 );
	dl_set_offsets( &cs, 0x000000, 0x000A00, 0x555555, 0x000500 );
	/*dl_set_offsets( &cs, 0x000000, 0x000A00, 0x555555, 0x000500 );
	dl_unknown_command( &cs );
	dl_set_offsets( &cs, 0x000000, 0x000A00, 0x555555, 0x000500 );*/
	dl_set_register( &cs, DL_REG_BLANK_SCREEN, 0x00 ); // enable output
	dl_set_register( &cs, DL_REG_SYNC, 0xFF );
	dl_sync_command( &cs );
	send( &cs, handle );

	sleep(1);

	//dl_dumpmem(handle,"dump1.log");

	// fill with a bunch of red
	printf("filling screen with red gradient..\n");
	rle_word red = { 0x00, 0x0000 };
	for (int i = 0; i < YRES; i++) {
		dl_gfx_rle( &cs, i*XRES*2,      0x00, &red );
		dl_gfx_rle( &cs, i*XRES*2+512,  0x00, &red );
		dl_gfx_rle( &cs, i*XRES*2+1024, 0x00, &red );
		red.value = (i/15) << 11;
	}
	dl_sync_command( &cs );
	send( &cs, handle );

	sleep(1);

	// grr. I'm pretty sure that I'm right about the stride register,
	// but I can't get it to have any effect...
	/*dl_set_register( &cs, DL_REG_SYNC, 0x00 );
	dl_set_address(  &cs, DL_ADDR_FB16_STRIDE, X*2 );
	dl_set_address(  &cs, DL_ADDR_FB8_STRIDE, X );
	dl_set_register( &cs, DL_REG_SYNC, 0xFF );
	dl_sync_command( &cs );
	send( &cs, handle );*/

	if (argc >= 2) {

		// fill with an image
		printf("filling screen with an image..\n");
		#define X 640
		#define Y 960

		uint8_t* image = read_rgb16(argv[1],X*Y);
		for (int i = 0; i < (X*Y)/256; i++) {
			dl_gfx_write( &cs, i*256*2, 0x00, image+(i*256*2) );
			if ((i % 100) == 0) {
				dl_sync_command( &cs );
				send( &cs, handle );
			}
		}
		dl_sync_command( &cs );
		send( &cs, handle );

		sleep(1);
	}

	// some vertical scrolling
	printf("doing vertical scrolling (why doesn't horizontal work?)..\n");
	for (int i = 0; i < YRES; i++) {
		dl_set_register( &cs, DL_REG_SYNC, 0x00 );
		dl_set_address(  &cs, DL_ADDR_FB16_START, i*XRES*2 );
		dl_set_register( &cs, DL_REG_SYNC, 0xFF );
		dl_sync_command( &cs );
		send( &cs, handle );
		usleep(5000);
	}

	//dl_dumpmem(handle,"dump2.log");

	sleep(1);

	// some memcopy
	printf("doing bitblt..\n\n");
	dl_set_offsets( &cs, 0x000000, 0x000A00, 0x555555, 0x000500 );
	for (int i = 0; i < 100; i++) {
		dl_gfx_copy( &cs, 0x500*(280+i)+320*2, 0x500*(380+i)+420*2, 100 );
	}
	dl_sync_command( &cs );
	send( &cs, handle );

	printf("goodbye.\n\n");
	usb_close( handle );
	destroy( &cs );
}

