diff --git a/engine/client/cl_ignore.c b/engine/client/cl_ignore.c index d87548fcf..a39b6fb29 100644 --- a/engine/client/cl_ignore.c +++ b/engine/client/cl_ignore.c @@ -93,7 +93,7 @@ cvar_t ignore_spec = CVAR("ignore_spec", "0"); cvar_t ignore_qizmo_spec = CVAR("ignore_qizmo_spec", "0"); cvar_t ignore_mode = CVAR("ignore_mode", "0"); cvar_t ignore_flood_duration = CVARD("ignore_flood_duration", "4", "Time limit for inbound messages to be considered duplicates."); -cvar_t ignore_flood = CVARD("ignore_flood", "0", "Provides a way to reduce inbound spam from flooding out your chat (dupe messages are ignored).\n0: No inbound flood protection.\n1: Duplicate non-team messages will be filtered.\n2: ALL duplicate messages will be filtered\n"); +cvar_t ignore_flood = CVARD("ignore_flood", "0", "Provides a way to reduce inbound spam from flooding out your chat (dupe messages are ignored).\n0: No inbound flood protection.\n1: Duplicate non-team messages will be filtered.\n2: ALL duplicate messages will be filtered"); cvar_t ignore_opponents = CVAR("ignore_opponents", "0"); char ignoreteamlist[MAX_TEAMIGNORELIST][16 + 1]; diff --git a/engine/client/cl_main.c b/engine/client/cl_main.c index e50b2c95e..77c405fdc 100644 --- a/engine/client/cl_main.c +++ b/engine/client/cl_main.c @@ -3052,13 +3052,18 @@ void CL_ConnectionlessPacket (void) Con_TPrintf ("redirect to %s\n", data); if (NET_StringToAdr(data, PORT_DEFAULTSERVER, &adr)) { - data = "\xff\xff\xff\xffgetchallenge\n"; - if (NET_CompareAdr(&connectinfo.adr, &net_from)) { - connectinfo.istransfer = true; - connectinfo.adr = adr; - NET_SendPacket (cls.sockets, strlen(data), data, &adr); + if (!NET_EnsureRoute(cls.sockets, "redir", cls.servername, &connectinfo.adr)) + Con_Printf ("Unable to redirect to %s\n", data); + else + { + connectinfo.istransfer = true; + connectinfo.adr = adr; + + data = "\xff\xff\xff\xffgetchallenge\n"; + NET_SendPacket (cls.sockets, strlen(data), data, &adr); + } } } return; diff --git a/engine/client/console.c b/engine/client/console.c index c99bd9e5b..0a68dd192 100644 --- a/engine/client/console.c +++ b/engine/client/console.c @@ -33,7 +33,7 @@ console_t *con_chat; // points to a chat console #define Font_ScreenWidth() (vid.pixelwidth) static int Con_DrawProgress(int left, int right, int y); -static int Con_DrawConsoleLines(console_t *con, conline_t *l, int sx, int ex, int y, int top, int selactive, int selsx, int selex, int selsy, int seley, float lineagelimit); +static int Con_DrawConsoleLines(console_t *con, conline_t *l, float displayscroll, int sx, int ex, int y, int top, int selactive, int selsx, int selex, int selsy, int seley, float lineagelimit); #ifdef QTERM #include @@ -971,7 +971,7 @@ void Con_PrintCon (console_t *con, const char *txt, unsigned int parseflags) con->current->newer = reuse; con->current = reuse; con->current->length = 0; - if (con->display == con->current->older) + if (con->display == con->current->older && con->displayscroll==0) con->display = con->current; break; default: @@ -980,6 +980,8 @@ void Con_PrintCon (console_t *con, const char *txt, unsigned int parseflags) con->current->length = 0; con->cr = false; } + if (!con->current->numlines) + con->current->numlines = 1; if (!con->current->length && con_timestamps.ival && !(parseflags & PFS_CENTERED)) { @@ -1394,7 +1396,7 @@ int Con_DrawInput (console_t *con, qboolean focused, int left, int right, int y, { if (con->footerline) { - y = Con_DrawConsoleLines(con, con->footerline, left, right, y, 0, selactive, selsx, selex, selsy, seley, 0); + y = Con_DrawConsoleLines(con, con->footerline, 0, left, right, y, 0, selactive, selsx, selex, selsy, seley, 0); } return y; //fixme: draw any unfinished lines of the current console instead. } @@ -1553,7 +1555,7 @@ int Con_DrawInput (console_t *con, qboolean focused, int left, int right, int y, /*if its getting completed to something, show some help about the command that is going to be used*/ if (con->footerline) { - y = Con_DrawConsoleLines(con, con->footerline, left, right, y, 0, selactive, selsx, selex, selsy, seley, 0); + y = Con_DrawConsoleLines(con, con->footerline, 0, left, right, y, 0, selactive, selsx, selex, selsy, seley, 0); } /*just above that, we have the tab completion list*/ @@ -1601,7 +1603,7 @@ int Con_DrawInput (console_t *con, qboolean focused, int left, int right, int y, } if (con->completionline->length) - y = Con_DrawConsoleLines(con, con->completionline, left, right, y, 0, selactive, selsx, selex, selsy, seley, 0); + y = Con_DrawConsoleLines(con, con->completionline, 0, left, right, y, 0, selactive, selsx, selex, selsy, seley, 0); } return y; @@ -2079,9 +2081,21 @@ int Con_DrawAlternateConsoles(int lines) return y; } +static void Con_DrawImageClip(float x, float y, float w, float h, float bottom, shader_t *pic) +{ + if (bottom < y+h) + { + if (bottom <= y) + return; + R2D_Image(x,y,w,bottom-y,0,0,1,(bottom-y)/h,pic); + } + else + R2D_Image(x,y,w,h,0,0,1,1,pic); +} + //draws the conline_t list bottom-up within the width of the screen until the top of the screen is reached. //if text is selected, the selstartline globals will be updated, so make sure the lines persist or check them. -static int Con_DrawConsoleLines(console_t *con, conline_t *l, int sx, int ex, int y, int top, int selactive, int selsx, int selex, int selsy, int seley, float lineagelimit) +static int Con_DrawConsoleLines(console_t *con, conline_t *l, float displayscroll, int sx, int ex, int y, int top, int selactive, int selsx, int selex, int selsy, int seley, float lineagelimit) { int linecount; conchar_t *starts[64], *ends[sizeof(starts)/sizeof(starts[0])]; @@ -2090,17 +2104,28 @@ static int Con_DrawConsoleLines(console_t *con, conline_t *l, int sx, int ex, in int charh = Font_CharHeight(); unsigned int codeflags, codepoint; float alphaval = 1; + float chop; + + chop = displayscroll * Font_CharHeight(); if (l != con->completionline) if (l != con->footerline) if (l != con->current) { - y -= 8; + y -= Font_CharHeight(); // draw arrows to show the buffer is backscrolled for (x = sx ; xdefaulttextures->base = Image_TextureIsValid(strtoull(imgname, NULL, 0)); + if (pic && pic->defaulttextures->base) + { + if (!pic->defaulttextures->base->width || !pic->defaulttextures->base->height || !TEXLOADED(pic->defaulttextures->base)) + picw = pich = 64; + else if (pic->defaulttextures->base->width > pic->defaulttextures->base->height) + { + picw = 64; + pich = (64.0*pic->defaulttextures->base->height)/pic->defaulttextures->base->width; + } + else + { + picw = (64.0*pic->defaulttextures->base->width)/pic->defaulttextures->base->height; + pich = 64; + } + break; + } + } + + imgname = Info_ValueForKey(linkinfo, "img"); if (*imgname) { @@ -2305,23 +2355,27 @@ static int Con_DrawConsoleLines(console_t *con, conline_t *l, int sx, int ex, in if (texth > pich) { texth = pich + (texth-pich)/2; - R2D_Image(sx*szx, (y-texth)*szy, picw*szx, pich*szy, 0, 0, 1, 1, pic); + Con_DrawImageClip(sx*szx, (y-texth)*szy, picw*szx, pich*szy, (y-chop+Font_CharHeight())*szy, pic); pich = 0; //don't pad the text... } else { - R2D_Image(sx*szx, (y-pich)*szy, picw*szx, pich*szy, 0, 0, 1, 1, pic); + Con_DrawImageClip(sx*szx, (y-pich)*szy, picw*szx, pich*szy, (y-chop+Font_CharHeight())*szy, pic); pich -= texth; y-= pich/2; //skip some space above and below the text block, to keep the text and image aligned. + + if (chop) + chop -= pich/2; } if (R2D_Flush) R2D_Flush(); // if (selsx < picw && selex < picw) + l->numlines = ceil((texth+pich)/Font_CharHeight()); } - - l->numlines = linecount; + else + l->numlines = linecount; while(linecount-- > 0) { @@ -2330,6 +2384,15 @@ static int Con_DrawConsoleLines(console_t *con, conline_t *l, int sx, int ex, in y -= Font_CharHeight(); + if (chop) + { + chop -= Font_CharHeight(); + if (chop < 0) + chop = 0; + else + continue; + } + if (top && y < top) break; @@ -2526,6 +2589,8 @@ static int Con_DrawConsoleLines(console_t *con, conline_t *l, int sx, int ex, in break; } y -= pich/2; + if (chop) + chop -= pich/2; if (y < top) break; } @@ -2799,7 +2864,7 @@ void Con_DrawConsole (int lines, qboolean noback) l = con_current->display; - y = Con_DrawConsoleLines(con_current, l, sx, ex, y, top, selactive, selsx, selex, selsy, seley, 0); + y = Con_DrawConsoleLines(con_current, l, con_current->displayscroll, sx, ex, y, top, selactive, selsx, selex, selsy, seley, 0); if (!haveprogress && lines == vid.height) { @@ -3163,7 +3228,7 @@ void Con_DrawOneConsole(console_t *con, qboolean focused, struct font_s *font, f if (!con->display) con->display = con->current; - Con_DrawConsoleLines(con, con->display, x, sx, sy, y, selactive, selsx, selex, selsy, seley, lineagelimit); + Con_DrawConsoleLines(con, con->display, con->displayscroll, x, sx, sy, y, selactive, selsx, selex, selsy, seley, lineagelimit); Font_EndString(font); } diff --git a/engine/client/image.c b/engine/client/image.c index 4238a0547..98c145081 100644 --- a/engine/client/image.c +++ b/engine/client/image.c @@ -4,10 +4,6 @@ //#define PURGEIMAGES //somewhat experimental still. we're still flushing more than we should. -//FIXME -texid_t GL_FindTextureFallback (const char *identifier, unsigned int flags, void *fallback, int fallbackwidth, int fallbackheight, uploadfmt_t fallbackfmt); -//FIXME - #ifdef NPFTE //#define Con_Printf(f, ...) //hope you're on a littleendian machine @@ -57,7 +53,7 @@ char *r_defaultimageextensions = " pcx" //pcxes are the original gamedata of q2. So we don't want them to override pngs. #endif ; -static void Image_ChangeFormat(struct pendingtextureinfo *mips, unsigned int flags, uploadfmt_t origfmt); +static void Image_ChangeFormat(struct pendingtextureinfo *mips, unsigned int flags, uploadfmt_t origfmt, const char *imagename); static void QDECL R_ImageExtensions_Callback(struct cvar_s *var, char *oldvalue); cvar_t r_imageextensions = CVARCD("r_imageextensions", NULL, R_ImageExtensions_Callback, "The list of image file extensions which might exist on disk (note that this does not list all supported formats, only the extensions that should be searched for)."); cvar_t r_image_downloadsizelimit = CVARFD("r_image_downloadsizelimit", "131072", CVAR_NOTFROMSERVER, "The maximum allowed file size of images loaded from a web-based url. 0 disables completely, while empty imposes no limit."); @@ -78,7 +74,10 @@ static bucket_t *imagetablebuckets[256]; static hashtable_t imagetable; static image_t *imagelist; - +#ifdef DECOMPRESS_ASTC +#define ASTC_PUBLIC +#include "image_astc.h" +#endif @@ -127,7 +126,7 @@ static void GenerateXMPData(char *blob, size_t blobsize, int width, int height, typedef struct { //cm = colourmap char id_len; //0 char cm_type; //1 - char version; //2 + qbyte version; //2 char pad1; short cm_idx; //3 short cm_len; //5 @@ -256,7 +255,7 @@ static char *ReadGreyTargaFile (qbyte *data, int flen, tgaheader_t *tgahead, int //remember to free it //greyonly causes the function to fail if given anything but greyscale images //this is for detecting heightmaps instead of normalmaps. -qbyte *ReadTargaFile(qbyte *buf, int length, int *width, int *height, uploadfmt_t *format, qboolean greyonly, uploadfmt_t forceformat) +void *ReadTargaFile(qbyte *buf, int length, int *width, int *height, uploadfmt_t *format, qboolean greyonly, uploadfmt_t forceformat) { //tga files sadly lack a true magic header thing. unsigned char *data; @@ -265,8 +264,8 @@ qbyte *ReadTargaFile(qbyte *buf, int length, int *width, int *height, uploadfmt_ tgaheader_t tgaheader; //things are misaligned, so no pointer. - if (length < 18 || buf[1] > 1 || (buf[16] != 8 && buf[16] != 16 && buf[16] != 24 && buf[16] != 32)) - return NULL; //BUMMER! + if (length < 18 || buf[1] > 1) + return NULL; //probably not a tga... tgaheader.id_len = buf[0]; tgaheader.cm_type = buf[1]; @@ -290,9 +289,18 @@ qbyte *ReadTargaFile(qbyte *buf, int length, int *width, int *height, uploadfmt_ case 3: //Uncompressed, black and white images. case 9: //Runlength encoded color-mapped images. case 10: //Runlength encoded RGB images. - case 11: //Compressed, black and white images. + case 11: //Runlength encoded, black and white images. case 32: //Compressed color-mapped data, using Huffman, Delta, and runlength encoding. case 33: //Compressed color-mapped data, using Huffman, Delta, and runlength encoding. 4-pass quadtree-type process. + if (buf[16] != 8 && buf[16] != 16 && buf[16] != 24 && buf[16] != 32) + return NULL; //unsupported bitdepths + break; + case 0x82: //half-float rgb + case 0x83: //half-float greyscale + if (forceformat != PTI_INVALID) + return NULL; + if ((buf[16]&15) || buf[16]<16 || buf[16] > 16*4) + return NULL; //unsupported bitdepths break; default: return NULL; @@ -331,21 +339,37 @@ qbyte *ReadTargaFile(qbyte *buf, int length, int *width, int *height, uploadfmt_ } else if (tgaheader.version == 10 || tgaheader.version == 9 || tgaheader.version == 11) { - //9:paletted - //10:bgr(a) - //11:greyscale + //9:RLE paletted + //10:RLE bgr(a) + //11:RLE greyscale #undef getc #define getc(x) *data++ unsigned int row, rows=tgaheader.height, column, columns=tgaheader.width, packetHeader, packetSize, j; - qbyte *pixbuf, *targa_rgba=BZ_Malloc(rows*columns*((forceformat==PTI_L8)?1:4)), *inrow; + qbyte *pixbuf, *targa_rgba; + unsigned int inraw; qbyte blue, red, green, alphabyte; byte_vec4_t palette[256]; + enum + { + rle_p8, + rle_a1rgb5, + rle_bgr8, + rle_bgra8, + rle_l8, + rle_l8a8, + } rlemode; + int outbytes; *format = PTI_RGBX8; if (tgaheader.version == 9) { //RLE palette + if (tgaheader.bpp == 8) //FIXME: tgaheader.bpp can be 8, 15, or 16. + rlemode = rle_p8; + else + return NULL; + for (row = 0; row < 256; row++) { palette[row][0] = row; @@ -353,8 +377,6 @@ qbyte *ReadTargaFile(qbyte *buf, int length, int *width, int *height, uploadfmt_ palette[row][2] = row; palette[row][3] = 255; } - if (tgaheader.bpp != 8) //FIXME: tgaheader.bpp can be 8, 15, or 16. - return NULL; if (forceformat == PTI_L8 || forceformat == PTI_INVALID) *format = forceformat = PTI_L8; @@ -367,6 +389,8 @@ qbyte *ReadTargaFile(qbyte *buf, int length, int *width, int *height, uploadfmt_ qboolean grey = true; switch(tgaheader.cm_size) { + default: + return NULL; case 24: for (row = 0; row < tgaheader.cm_len; row++) { @@ -402,75 +426,96 @@ qbyte *ReadTargaFile(qbyte *buf, int length, int *width, int *height, uploadfmt_ } else if (tgaheader.version == 10) { //RLE truecolour - if (tgaheader.bpp == 8) + if (tgaheader.bpp == 16) + rlemode = rle_a1rgb5; + else if (tgaheader.bpp == 24) + rlemode = rle_bgr8; + else if (tgaheader.bpp == 32) + rlemode = rle_bgra8; + else return NULL; - *format = (tgaheader.bpp==32)?PTI_RGBA8:PTI_RGBX8; + *format = (tgaheader.bpp==24)?PTI_RGBX8:PTI_RGBA8; } else if (tgaheader.version == 11) { //RLE greyscale - for (row = 0; row < 256; row++) - { - palette[row][0] = row; - palette[row][1] = row; - palette[row][2] = row; - palette[row][3] = 255; - } - if (tgaheader.bpp != 8) + if (tgaheader.bpp == 8) + rlemode = rle_l8; + else if (tgaheader.bpp == 16) + rlemode = rle_l8a8; + else return NULL; - } + if (forceformat == PTI_L8) + *format = forceformat; + else if (rlemode==rle_l8a8) + *format = PTI_LLLA8; //should probably use PTI_L8A8, but the caller will know to optimise + else + *format = PTI_LLLX8; + } + else + return NULL; + + if (*format == PTI_L8) + outbytes = 1; + else if (*format == PTI_L8A8) + outbytes = 2; + else + outbytes = 4; + targa_rgba=BZ_Malloc(rows*columns*outbytes); for(row=rows; row-->0; ) { if (flipped) - pixbuf = targa_rgba + row*columns*((forceformat==PTI_L8)?1:4); + pixbuf = targa_rgba + row*columns*outbytes; else - pixbuf = targa_rgba + ((rows-1)-row)*columns*((forceformat==PTI_L8)?1:4); + pixbuf = targa_rgba + ((rows-1)-row)*columns*outbytes; for(column=0; column>2) *8; //red - green = (((inrow[1] & 0x03)<<3) + ((inrow[0] & 0xe0)>>5))*8; //green - blue = (inrow[0] & 0x1f)*8; //blue - alphabyte = (int)(inrow[1]&0x80)*2-1; //alpha? - break; - case 24: - blue = *data++; - green = *data++; - red = *data++; - alphabyte = 255; - break; - case 32: - blue = *data++; - green = *data++; - red = *data++; - alphabyte = *data++; - break; - default: - blue = 127; - green = 127; - red = 127; - alphabyte = 127; - break; + case rle_a1rgb5: + inraw = data[0] | (data[1]<<8); + data+=2; + alphabyte = (inraw&0x8000)?255:0; + red = ((inraw>>10)&0x1f)<<3; + green = ((inraw>>5)&0x1f)<<3; + blue = ((inraw>>0)&0x1f)<<3; + break; + case rle_bgr8: + blue = *data++; + green = *data++; + red = *data++; + alphabyte = 255; + break; + case rle_bgra8: + blue = *data++; + green = *data++; + red = *data++; + alphabyte = *data++; + break; } - if (forceformat!=PTI_L8) //keep colours + if (*format!=PTI_L8) //keep colours { for(j=0;j>2) *8; //red - green = (((inrow[1] & 0x03)<<3) + ((inrow[0] & 0xe0)>>5))*8; //green - blue = (inrow[0] & 0x1f)*8; //blue - alphabyte = (int)(inrow[1]&0x80)*2-1; //alpha? + case rle_p8: + blue = palette[*data][0]; + green = palette[*data][1]; + red = palette[*data][2]; + alphabyte = palette[*data][3]; + data++; + *pixbuf++ = red; + *pixbuf++ = green; + *pixbuf++ = blue; + *pixbuf++ = alphabyte; + break; + case rle_l8a8: + blue = green = red = *data++; + alphabyte = *data++; + *pixbuf++ = red; + *pixbuf++ = green; + *pixbuf++ = blue; + *pixbuf++ = alphabyte; + break; + case rle_l8: + blue = green = red = *data++; + *pixbuf++ = red; + *pixbuf++ = green; + *pixbuf++ = blue; + *pixbuf++ = 255; + break; + case rle_a1rgb5: + inraw = data[0] | (data[1]<<8); + data+=2; + alphabyte = (inraw&0x8000)?255:0; + red = ((inraw>>10)&0x1f)<<3; + green = ((inraw>>5)&0x1f)<<3; + blue = ((inraw>>0)&0x1f)<<3; - *pixbuf++ = red; - *pixbuf++ = green; - *pixbuf++ = blue; - *pixbuf++ = alphabyte; - break; - case 24: - blue = *data++; - green = *data++; - red = *data++; - *pixbuf++ = red; - *pixbuf++ = green; - *pixbuf++ = blue; - *pixbuf++ = 255; - break; - case 32: - blue = *data++; - green = *data++; - red = *data++; - alphabyte = *data++; - *pixbuf++ = red; - *pixbuf++ = green; - *pixbuf++ = blue; - *pixbuf++ = alphabyte; - break; - default: - blue = 127; - green = 127; - red = 127; - alphabyte = 127; - break; + *pixbuf++ = red; + *pixbuf++ = green; + *pixbuf++ = blue; + *pixbuf++ = alphabyte; + break; + case rle_bgr8: + blue = *data++; + green = *data++; + red = *data++; + *pixbuf++ = red; + *pixbuf++ = green; + *pixbuf++ = blue; + *pixbuf++ = 255; + break; + case rle_bgra8: + blue = *data++; + green = *data++; + red = *data++; + alphabyte = *data++; + *pixbuf++ = red; + *pixbuf++ = green; + *pixbuf++ = blue; + *pixbuf++ = alphabyte; + break; } column++; if (column==columns) @@ -590,44 +645,47 @@ qbyte *ReadTargaFile(qbyte *buf, int length, int *width, int *height, uploadfmt_ { for(j=0;j>2) *8; //red - green = (((inrow[1] & 0x03)<<3) + ((inrow[0] & 0xe0)>>5))*8; //green - blue = (inrow[0] & 0x1f)*8; //blue - alphabyte = (int)(inrow[1]&0x80)*2-1; //alpha? + case rle_p8: + blue = palette[*data][0]; + green = palette[*data][1]; + red = palette[*data][2]; + *pixbuf++ = (blue + green + red)/3; + data++; + break; + case rle_l8a8: + blue = green = red = *data++; + alphabyte = *data++; + *pixbuf++ = green; + break; + case rle_l8: + blue = green = red = *data++; + *pixbuf++ = green; + break; + case rle_a1rgb5: + inraw = data[0] | (data[1]<<8); + data+=2; + alphabyte = (inraw&0x8000)?255:0; + red = ((inraw>>10)&0x1f)<<3; + green = ((inraw>>5)&0x1f)<<3; + blue = ((inraw>>0)&0x1f)<<3; - *pixbuf++ = red*NTSC_RED + green*NTSC_GREEN + blue*NTSC_BLUE; - break; - case 24: - blue = *data++; - green = *data++; - red = *data++; - *pixbuf++ = red*NTSC_RED + green*NTSC_GREEN + blue*NTSC_BLUE; - break; - case 32: - blue = *data++; - green = *data++; - red = *data++; - alphabyte = *data++; - *pixbuf++ = red*NTSC_RED + green*NTSC_GREEN + blue*NTSC_BLUE; - break; - default: - blue = 127; - green = 127; - red = 127; - alphabyte = 127; - break; + *pixbuf++ = red*NTSC_RED + green*NTSC_GREEN + blue*NTSC_BLUE; + break; + case rle_bgr8: + blue = *data++; + green = *data++; + red = *data++; + *pixbuf++ = red*NTSC_RED + green*NTSC_GREEN + blue*NTSC_BLUE; + break; + case rle_bgra8: + blue = *data++; + green = *data++; + red = *data++; + alphabyte = *data++; + *pixbuf++ = red*NTSC_RED + green*NTSC_GREEN + blue*NTSC_BLUE; + break; } column++; if (column==columns) @@ -651,15 +709,116 @@ qbyte *ReadTargaFile(qbyte *buf, int length, int *width, int *height, uploadfmt_ return targa_rgba; } + else if ((tgaheader.version == 0x82||tgaheader.version == 0x83) && forceformat && forceformat!=PTI_RGBA16F) + Con_Printf("HTGA: required output format is not half-float\n"); + else if ((tgaheader.version == 0x82||tgaheader.version == 0x83) && !(tgaheader.bpp&15) && tgaheader.bpp>=16 && tgaheader.bpp<=16*4) + { //packed r[g[b[a]]]f + unsigned short *initbuf, *inrow, *outrow; + int x, y, mul; + + if (tgaheader.version == 0x83 && tgaheader.bpp==16) + *format = forceformat = PTI_R16F; + else + *format = forceformat = PTI_RGBA16F; //gray+alpha needs to be rgbaf + + initbuf = BZ_Malloc(tgaheader.height*tgaheader.width* ((forceformat==PTI_R16F)?2:8)); + + mul = tgaheader.bpp/8; +//flip +convert to 32 bit + outrow = &initbuf[(int)(0)*tgaheader.width*mul]; + for (y = 0; y < tgaheader.height; y+=1) + { + if (flipped) + inrow = (unsigned short*)&data[(int)(tgaheader.height-y-1)*tgaheader.width*mul]; + else + inrow = (unsigned short*)&data[(int)(y)*tgaheader.width*mul]; + + switch(mul) + { + default: //bug! + for (x = 0; x < tgaheader.width; x+=1) + { + *outrow++ = 0; + *outrow++ = 0; + *outrow++ = 0; + *outrow++ = 0xf<<10; + } + break; + case 2: //Lum + if (forceformat == PTI_R16F) + { + for (x = 0; x < tgaheader.width; x+=1) + *outrow++ = *inrow++; + } + else + { + for (x = 0; x < tgaheader.width; x+=1) + { + *outrow++ = *inrow; + *outrow++ = *inrow; + *outrow++ = *inrow; + *outrow++ = 0xf<<10; //1.0 + inrow+=1; + } + } + break; + case 4: + if (tgaheader.version == 0x83) + { //treat as LumAlpha + for (x = 0; x < tgaheader.width; x+=1) + { + *outrow++ = inrow[0]; + *outrow++ = inrow[0]; + *outrow++ = inrow[0]; + *outrow++ = inrow[1]; + inrow+=2; + } + } + else + { //RG + for (x = 0; x < tgaheader.width; x+=1) + { + *outrow++ = inrow[0]; + *outrow++ = inrow[1]; + *outrow++ = 0; + *outrow++ = 0xf<<10; //1.0 + inrow+=2; + } + } + break; + case 6: //BGR + for (x = 0; x < tgaheader.width; x+=1) + { + *outrow++ = inrow[2]; + *outrow++ = inrow[1]; + *outrow++ = inrow[0]; + *outrow++ = 0xf<<10; //1.0 + inrow+=3; + } + break; + case 8: //BGRA16F, swizzle to rgba + for (x = 0; x < tgaheader.width; x+=1) + { + *outrow++ = inrow[2]; + *outrow++ = inrow[1]; + *outrow++ = inrow[0]; + *outrow++ = inrow[3]; + inrow+=4; + } + break; + } + } + return initbuf; + } else if (tgaheader.version == 2) { //packed format - qbyte *initbuf=BZ_Malloc(tgaheader.height*tgaheader.width* ((forceformat==PTI_L8)?1:4)); - qbyte *inrow, *outrow; + qbyte *initbuf, *inrow, *outrow; int x, y, mul; qbyte blue, red, green; if (tgaheader.bpp == 8) return NULL; + initbuf=BZ_Malloc(tgaheader.height*tgaheader.width* ((forceformat==PTI_L8)?1:4)); mul = tgaheader.bpp/8; //flip +convert to 32 bit @@ -794,7 +953,7 @@ qboolean WriteTGA(char *filename, enum fs_relative fsroot, const qbyte *fte_rest qboolean success = false; size_t c, i; vfsfile_t *vfs; - if (fmt != TF_BGRA32 && fmt != TF_RGB24 && fmt != TF_RGBA32 && fmt != TF_BGR24 && fmt != TF_RGBX32 && fmt != TF_BGRX32) + if (fmt != PTI_BGRA8 && fmt != PTI_RGB8 && fmt != PTI_RGBA8 && fmt != PTI_BGR8 && fmt != PTI_RGBX8 && fmt != PTI_BGRX8 && fmt != PTI_R16F && fmt != PTI_RGBA16F) return false; FS_CreatePath(filename, fsroot); vfs = FS_OpenVFS(filename, "wb", fsroot); @@ -805,26 +964,43 @@ qboolean WriteTGA(char *filename, enum fs_relative fsroot, const qbyte *fte_rest unsigned char header[18]; memset (header, 0, 18); - if (fmt == TF_BGRA32 || fmt == TF_RGBA32) + if (fmt == PTI_RGBA16F) { - rgb = fmt==TF_RGBA32; - ipx = 4; - opx = 4; + header[2] = 0x82; + opx = 8; + ipx = 8; + rgb = true; } - else if (fmt == TF_RGBX32 || fmt == TF_BGRX32) + else if (fmt == PTI_R16F) { - rgb = fmt==TF_RGBX32; - ipx = 4; - opx = 3; + header[2] = 0x83; + opx = 2; + ipx = 2; + rgb = false; } else { - rgb = fmt==TF_RGB24; - ipx = 3; - opx = 3; + header[2] = 2; // uncompressed type + if (fmt == PTI_BGRA8 || fmt == PTI_RGBA8 || fmt==PTI_LLLA8) + { + rgb = fmt==TF_RGBA32; + ipx = 4; + opx = 4; + } + else if (fmt == PTI_RGBX8 || fmt == PTI_BGRX8 || fmt==PTI_LLLX8) + { + rgb = fmt==PTI_RGBX8; + ipx = 4; + opx = 3; + } + else + { + rgb = fmt==PTI_RGB8; + ipx = 3; + opx = 3; + } } - header[2] = 2; // uncompressed type header[12] = width&255; header[13] = width>>8; header[14] = height&255; @@ -857,12 +1033,28 @@ qboolean WriteTGA(char *filename, enum fs_relative fsroot, const qbyte *fte_rest if (rgb) { //rgb24, rgbx32, rgba32 // compact, and swap - c = (size_t)width*height; - for (i=0 ; i= PTI_ASTC_4X4_LDR && encoding <= PTI_ASTC_12X12_LDR) + { + for (face = 0; face < header->numberoffaces; face++) + { + if (ASTC_BlocksAreHDR(mips->mip[face].data, mips->mip[face].datasize, blockwidth, blockheight, 1)) + { //convert it to one of the hdr formats if we can. + mips->encoding = PTI_ASTC_4X4_HDR+(encoding-PTI_ASTC_4X4_LDR); + break; + } + } + } +#endif + + return mips; +} +#endif + +#ifdef IMAGEFMT_ASTC +static struct pendingtextureinfo *Image_ReadASTCFile(unsigned int flags, const char *fname, qbyte *filedata, size_t filesize) +{ + struct pendingtextureinfo *mips; + int encoding = PTI_INVALID, blockbytes, blockwidth, blockheight; + static const struct { + int w, h, d; + int fmt; + } sizes[] = + { + {4,4,1,PTI_ASTC_4X4_LDR}, + {5,4,1,PTI_ASTC_5X4_LDR}, + {5,5,1,PTI_ASTC_5X5_LDR}, + {6,5,1,PTI_ASTC_6X5_LDR}, + {6,6,1,PTI_ASTC_6X6_LDR}, + {8,5,1,PTI_ASTC_8X5_LDR}, + {8,6,1,PTI_ASTC_8X6_LDR}, + {10,5,1,PTI_ASTC_10X5_LDR}, + {10,6,1,PTI_ASTC_10X6_LDR}, + {8,8,1,PTI_ASTC_8X8_LDR}, + {10,8,1,PTI_ASTC_10X8_LDR}, + {10,10,1,PTI_ASTC_10X10_LDR}, + {12,10,1,PTI_ASTC_12X10_LDR}, + {12,12,1,PTI_ASTC_12X12_LDR}, + }; + int i; + int size[3] = { + filedata[7]|(filedata[8]<<8)|(filedata[9]<<16), + filedata[10]|(filedata[11]<<8)|(filedata[12]<<16), + filedata[13]|(filedata[14]<<8)|(filedata[15]<<16)}; + for (i = 0; i < countof(sizes); i++) + { + if (sizes[i].w == filedata[4] && sizes[i].h == filedata[5] && sizes[i].d == filedata[6]) + { + encoding = sizes[i].fmt; + break; + } + } + if (!encoding) + return NULL; //block size not known + Image_BlockSizeForEncoding(encoding, &blockbytes, &blockwidth, &blockheight); + if (16+((size[0]+blockwidth-1)/blockwidth)*((size[1]+blockheight-1)/blockheight)*blockbytes != filesize) + return NULL; //err, not the right size! + + mips = Z_Malloc(sizeof(*mips)); + mips->mipcount = 1; //this format doesn't support mipmaps. so there's only one level. + mips->type = PTI_2D; + mips->extrafree = filedata; + mips->encoding = encoding; + mips->mip[0].data = filedata+16; + mips->mip[0].datasize = filesize-16; + mips->mip[0].width = size[0]; + mips->mip[0].height = size[1]; + mips->mip[0].depth = size[2]; + mips->mip[0].needfree = false; + +#ifdef ASTC_WITH_HDRTEST + if (ASTC_BlocksAreHDR(mips->mip[0].data, mips->mip[0].datasize, blockwidth, blockheight, 1)) + { //convert it to one of the hdr formats if we can. + mips->encoding = PTI_ASTC_4X4_HDR+(encoding-PTI_ASTC_4X4_LDR); + } +#endif return mips; } #endif @@ -4035,6 +4320,35 @@ static struct pendingtextureinfo *Image_ReadDDSFile(unsigned int flags, const ch encoding = PTI_BC7_RGBA_SRGB; break; + case 134: encoding = PTI_ASTC_4X4_LDR; break; + case 135: encoding = PTI_ASTC_4X4_SRGB; break; + case 138: encoding = PTI_ASTC_5X4_LDR; break; + case 139: encoding = PTI_ASTC_5X4_SRGB; break; + case 142: encoding = PTI_ASTC_5X5_LDR; break; + case 143: encoding = PTI_ASTC_5X5_SRGB; break; + case 146: encoding = PTI_ASTC_6X5_LDR; break; + case 147: encoding = PTI_ASTC_6X5_SRGB; break; + case 150: encoding = PTI_ASTC_6X6_LDR; break; + case 151: encoding = PTI_ASTC_6X6_SRGB; break; + case 154: encoding = PTI_ASTC_8X5_LDR; break; + case 155: encoding = PTI_ASTC_8X5_SRGB; break; + case 158: encoding = PTI_ASTC_8X6_LDR; break; + case 159: encoding = PTI_ASTC_8X6_SRGB; break; + case 162: encoding = PTI_ASTC_8X8_LDR; break; + case 163: encoding = PTI_ASTC_8X8_SRGB; break; + case 166: encoding = PTI_ASTC_10X5_LDR; break; + case 167: encoding = PTI_ASTC_10X5_SRGB; break; + case 170: encoding = PTI_ASTC_10X6_LDR; break; + case 171: encoding = PTI_ASTC_10X6_SRGB; break; + case 174: encoding = PTI_ASTC_10X8_LDR; break; + case 175: encoding = PTI_ASTC_10X8_SRGB; break; + case 178: encoding = PTI_ASTC_10X10_LDR; break; + case 179: encoding = PTI_ASTC_10X10_SRGB; break; + case 182: encoding = PTI_ASTC_12X10_LDR; break; + case 183: encoding = PTI_ASTC_12X10_SRGB; break; + case 186: encoding = PTI_ASTC_12X12_LDR; break; + case 187: encoding = PTI_ASTC_12X12_SRGB; break; + default: Con_Printf("Unsupported dds10 dxgi in %s - %u\n", fname, fmt10header.dxgiformat); return NULL; @@ -4185,20 +4499,20 @@ qboolean Image_WriteDDSFile(const char *filename, enum fs_relative fsroot, struc case PTI_EAC_R11_SNORM: case PTI_EAC_RG11: case PTI_EAC_RG11_SNORM: - case PTI_ASTC_4X4: - case PTI_ASTC_5X4: - case PTI_ASTC_5X5: - case PTI_ASTC_6X5: - case PTI_ASTC_6X6: - case PTI_ASTC_8X5: - case PTI_ASTC_8X6: - case PTI_ASTC_10X5: - case PTI_ASTC_10X6: - case PTI_ASTC_8X8: - case PTI_ASTC_10X8: - case PTI_ASTC_10X10: - case PTI_ASTC_12X10: - case PTI_ASTC_12X12: + case PTI_ASTC_4X4_LDR: + case PTI_ASTC_5X4_LDR: + case PTI_ASTC_5X5_LDR: + case PTI_ASTC_6X5_LDR: + case PTI_ASTC_6X6_LDR: + case PTI_ASTC_8X5_LDR: + case PTI_ASTC_8X6_LDR: + case PTI_ASTC_10X5_LDR: + case PTI_ASTC_10X6_LDR: + case PTI_ASTC_8X8_LDR: + case PTI_ASTC_10X8_LDR: + case PTI_ASTC_10X10_LDR: + case PTI_ASTC_12X10_LDR: + case PTI_ASTC_12X12_LDR: case PTI_ASTC_4X4_SRGB: case PTI_ASTC_5X4_SRGB: case PTI_ASTC_5X5_SRGB: @@ -4212,7 +4526,21 @@ qboolean Image_WriteDDSFile(const char *filename, enum fs_relative fsroot, struc case PTI_ASTC_10X8_SRGB: case PTI_ASTC_10X10_SRGB: case PTI_ASTC_12X10_SRGB: - case PTI_ASTC_12X12_SRGB: return false; //unsupported + case PTI_ASTC_12X12_SRGB: + case PTI_ASTC_4X4_HDR: + case PTI_ASTC_5X4_HDR: + case PTI_ASTC_5X5_HDR: + case PTI_ASTC_6X5_HDR: + case PTI_ASTC_6X6_HDR: + case PTI_ASTC_8X5_HDR: + case PTI_ASTC_8X6_HDR: + case PTI_ASTC_10X5_HDR: + case PTI_ASTC_10X6_HDR: + case PTI_ASTC_8X8_HDR: + case PTI_ASTC_10X8_HDR: + case PTI_ASTC_10X10_HDR: + case PTI_ASTC_12X10_HDR: + case PTI_ASTC_12X12_HDR: return false; //unsupported case PTI_BC1_RGB: case PTI_BC1_RGBA: h10.dxgiformat = 71/*DXGI_FORMAT_BC1_UNORM*/; break; case PTI_BC1_RGB_SRGB: @@ -5140,6 +5468,9 @@ static void Image_GenerateMips(struct pendingtextureinfo *mips, unsigned int fla if (flags & IF_NOMIPMAP) return; + if (sh_config.can_genmips && mips->encoding != PTI_P8) + return; + switch(mips->encoding) { case PTI_P8: @@ -5165,8 +5496,6 @@ static void Image_GenerateMips(struct pendingtextureinfo *mips, unsigned int fla } return; case PTI_R8: - if (sh_config.can_mipcap) - return; //if we can cap mips, do that. it'll save lots of expensive lookups and uglyness. for (mip = mips->mipcount; mip < 32; mip++) { mips->mip[mip].width = mips->mip[mip-1].width >> 1; @@ -6228,22 +6557,22 @@ static void Image_Decode_EAC8U_Block_Internal(qbyte *fte_restrict in, qbyte *fte #undef EAC_Row #undef EAC_Pix } -static void Image_Decode_ETC2_RGB8_Block(qbyte *fte_restrict in, pixel32_t *fte_restrict out, int w) +static void Image_Decode_ETC2_RGB8_Block(qbyte *fte_restrict in, pixel32_t *fte_restrict out, int w, uploadfmt_t fmt) { Image_Decode_ETC2_Block_Internal(in, out, w, false); } //punchthrough alpha works by removing interleaved mode releasing a bit that says whether a block can have alpha=0, . -static void Image_Decode_ETC2_RGB8A1_Block(qbyte *fte_restrict in, pixel32_t *fte_restrict out, int w) +static void Image_Decode_ETC2_RGB8A1_Block(qbyte *fte_restrict in, pixel32_t *fte_restrict out, int w, uploadfmt_t fmt) { Image_Decode_ETC2_Block_Internal(in, out, w, true); } //ETC2 RGBA's alpha and R11(and RG11) work the same way as each other, but with varying extra blocks with either 8 or 11 bits of valid precision. -static void Image_Decode_ETC2_RGB8A8_Block(qbyte *fte_restrict in, pixel32_t *fte_restrict out, int w) +static void Image_Decode_ETC2_RGB8A8_Block(qbyte *fte_restrict in, pixel32_t *fte_restrict out, int w, uploadfmt_t fmt) { Image_Decode_ETC2_Block_Internal(in+8, out, w, false); Image_Decode_EAC8U_Block_Internal(in, out->v+3, w*4, false); } -static void Image_Decode_EAC_R11U_Block(qbyte *fte_restrict in, pixel32_t *fte_restrict out, int w) +static void Image_Decode_EAC_R11U_Block(qbyte *fte_restrict in, pixel32_t *fte_restrict out, int w, uploadfmt_t fmt) { pixel32_t r; int i = 0; @@ -6252,7 +6581,7 @@ static void Image_Decode_EAC_R11U_Block(qbyte *fte_restrict in, pixel32_t *fte_r out[w*0+i] = out[w*1+i] = out[w*2+i] = out[w*3+i] = r; Image_Decode_EAC8U_Block_Internal(in, out->v, w*4, false); } -static void Image_Decode_EAC_RG11U_Block(qbyte *fte_restrict in, pixel32_t *fte_restrict out, int w) +static void Image_Decode_EAC_RG11U_Block(qbyte *fte_restrict in, pixel32_t *fte_restrict out, int w, uploadfmt_t fmt) { pixel32_t r; int i = 0; @@ -6300,15 +6629,15 @@ static void Image_Decode_S3TC_Block_Internal(qbyte *fte_restrict in, pixel32_t * out += w; BC1_Row(out, 12); } -static void Image_Decode_BC1_Block(qbyte *fte_restrict in, pixel32_t *fte_restrict out, int w) +static void Image_Decode_BC1_Block(qbyte *fte_restrict in, pixel32_t *fte_restrict out, int w, uploadfmt_t fmt) { Image_Decode_S3TC_Block_Internal(in, out, w, 0xff); } -static void Image_Decode_BC1A_Block(qbyte *fte_restrict in, pixel32_t *fte_restrict out, int w) +static void Image_Decode_BC1A_Block(qbyte *fte_restrict in, pixel32_t *fte_restrict out, int w, uploadfmt_t fmt) { Image_Decode_S3TC_Block_Internal(in, out, w, 0); } -static void Image_Decode_BC2_Block(qbyte *fte_restrict in, pixel32_t *fte_restrict out, int w) +static void Image_Decode_BC2_Block(qbyte *fte_restrict in, pixel32_t *fte_restrict out, int w, uploadfmt_t fmt) { Image_Decode_S3TC_Block_Internal(in+8, out, w, 0xff); @@ -6392,49 +6721,30 @@ static void Image_Decode_RGTC_Block_Internal(qbyte *fte_restrict in, qbyte *fte_ } #ifdef DECOMPRESS_S3TC //s3tc rgb channel, with an rgtc alpha channel that depends upon both encodings (really the origin of rgtc, but mneh). -static void Image_Decode_BC3_Block(qbyte *fte_restrict in, pixel32_t *fte_restrict out, int w) +static void Image_Decode_BC3_Block(qbyte *fte_restrict in, pixel32_t *fte_restrict out, int w, uploadfmt_t fmt) { Image_Decode_S3TC_Block_Internal(in+8, out, w, 0xff); Image_Decode_RGTC_Block_Internal(in, out->v+3, w*4, false); } #endif -static void Image_Decode_BC4U_Block(qbyte *fte_restrict in, pixel32_t *fte_restrict out, int w) +static void Image_Decode_BC4_Block(qbyte *fte_restrict in, pixel32_t *fte_restrict out, int w, uploadfmt_t fmt) { //BC4: BC3's alpha channel but used as red only. pixel32_t r; int i = 0; Vector4Set(r.v, 0, 0, 0, 0xff); for (i = 0; i < 4; i++) out[w*0+i] = out[w*1+i] = out[w*2+i] = out[w*3+i] = r; - Image_Decode_RGTC_Block_Internal(in, out->v+0, w*4, false); + Image_Decode_RGTC_Block_Internal(in, out->v+0, w*4, fmt==PTI_BC4_R8_SNORM); } -static void Image_Decode_BC4S_Block(qbyte *fte_restrict in, pixel32_t *fte_restrict out, int w) -{ //BC4: BC3's alpha channel but used as red only. - pixel32_t r; - int i = 0; - Vector4Set(r.v, 0, 0, 0, 0xff); - for (i = 0; i < 4; i++) - out[w*0+i] = out[w*1+i] = out[w*2+i] = out[w*3+i] = r; - Image_Decode_RGTC_Block_Internal(in, out->v+0, w*4, true); -} -static void Image_Decode_BC5U_Block(qbyte *fte_restrict in, pixel32_t *fte_restrict out, int w) +static void Image_Decode_BC5_Block(qbyte *fte_restrict in, pixel32_t *fte_restrict out, int w, uploadfmt_t fmt) { //BC5: two of BC3's alpha channels but used as red+green only. pixel32_t r; int i = 0; Vector4Set(r.v, 0, 0, 0, 0xff); for (i = 0; i < 4; i++) out[w*0+i] = out[w*1+i] = out[w*2+i] = out[w*3+i] = r; - Image_Decode_RGTC_Block_Internal(in+0, out->v+0, w*4, false); - Image_Decode_RGTC_Block_Internal(in+8, out->v+1, w*4, false); -} -static void Image_Decode_BC5S_Block(qbyte *fte_restrict in, pixel32_t *fte_restrict out, int w) -{ //BC5: two of BC3's alpha channels but used as red+green only. - pixel32_t r; - int i = 0; - Vector4Set(r.v, 0, 0, 0, 0xff); - for (i = 0; i < 4; i++) - out[w*0+i] = out[w*1+i] = out[w*2+i] = out[w*3+i] = r; - Image_Decode_RGTC_Block_Internal(in+0, out->v+0, w*4, true); - Image_Decode_RGTC_Block_Internal(in+8, out->v+1, w*4, true); + Image_Decode_RGTC_Block_Internal(in+0, out->v+0, w*4, fmt==PTI_BC5_RG8_SNORM); + Image_Decode_RGTC_Block_Internal(in+8, out->v+1, w*4, fmt==PTI_BC5_RG8_SNORM); } #endif @@ -6455,8 +6765,9 @@ fte_inlinestatic int ReadBitsL(qbyte *in, int *bit, int n) int r = ReadBits(in, bit, 8); return (r)|(ReadBits(in, bit, n-8)<<8); } -static void Image_Decode_BC6_Block(qbyte *fte_restrict in, pixel64_t *fte_restrict out, int w, qboolean signextend) +static void Image_Decode_BC6_Block(qbyte *fte_restrict in, pixel64_t *fte_restrict out, int w, uploadfmt_t fmt) { + qboolean signextend = fmt==PTI_BC6_RGB_SFLOAT; static const int anchors[32] = { 15,15,15,15, @@ -6550,6 +6861,14 @@ static void Image_Decode_BC6_Block(qbyte *fte_restrict in, pixel64_t *fte_restri if (mode >= 2) mode |=ReadBits(in, &bit, 3)<<2; + //n[a:b] + //n is the output name (number=group, r/g/b=0/1/2 channel) + //a:b is the inclusive bit range, typically little-endian input + //so bit counts are a+1-b, shifted up by b. + //if b is ommitted then its equivelent to a (read as a:a, or in other words a single bit shifted up by b) + //if its backwards then the bits are big-endian for some reason and need to be switched (rare, handled here by reading individual bits) + //bit counts larger than 9 may need to read from more than two bytes, which requires special handling, hence the alternative function. + //it is hoped that the compiler will be able to inline these into trivial mask+shifts for less code than it would take to call ReadBits, at least when its from a single byte. switch(mode) { case 0: //1 @@ -6850,14 +7169,14 @@ static void Image_Decode_BC6_Block(qbyte *fte_restrict in, pixel64_t *fte_restri rgb[0][1] |= ReadBitsL(in, &bit,10)<<0; //g0[9:0], rgb[0][2] |= ReadBitsL(in, &bit,10)<<0; //b0[9:0], rgb[1][0] |= ReadBits(in, &bit, 8)<<0; //r1[7:0], - rgb[0][0] |= ReadBits(in, &bit, 1)<<11; //r0[11], - rgb[0][0] |= ReadBits(in, &bit, 1)<<10; //r0[10], + rgb[0][0] |=(ReadBits(in, &bit, 1)<<11) //r0[10:11], + | (ReadBits(in, &bit, 1)<<10); rgb[1][1] |= ReadBits(in, &bit, 8)<<0; //g1[7:0], - rgb[0][1] |= ReadBits(in, &bit, 1)<<11; //g0[11], - rgb[0][1] |= ReadBits(in, &bit, 1)<<10; //g0[10], + rgb[0][1] |=(ReadBits(in, &bit, 1)<<11) //g0[10:11], + | (ReadBits(in, &bit, 1)<<10); rgb[1][2] |= ReadBits(in, &bit, 8)<<0; //b1[7:0], - rgb[0][2] |= ReadBits(in, &bit, 1)<<11; //b0[11], - rgb[0][2] |= ReadBits(in, &bit, 1)<<10; //b0[10] + rgb[0][2] |=(ReadBits(in, &bit, 1)<<11) //b0[10:11], + | (ReadBits(in, &bit, 1)<<10); shapeindex = 0; break; case 15: //14 @@ -6869,11 +7188,26 @@ static void Image_Decode_BC6_Block(qbyte *fte_restrict in, pixel64_t *fte_restri rgb[0][1] |= ReadBitsL(in, &bit,10)<<0; //g0[9:0], rgb[0][2] |= ReadBitsL(in, &bit,10)<<0; //b0[9:0], rgb[1][0] |= ReadBits(in, &bit, 4)<<0; //r1[3:0], - rgb[0][0] |= ReadBits(in, &bit, 6)<<10; //r0[10:15], + rgb[0][0] |=(ReadBits(in, &bit, 1)<<15) //r0[10:15], + | (ReadBits(in, &bit, 1)<<14) + | (ReadBits(in, &bit, 1)<<13) + | (ReadBits(in, &bit, 1)<<12) + | (ReadBits(in, &bit, 1)<<11) + | (ReadBits(in, &bit, 1)<<10); rgb[1][1] |= ReadBits(in, &bit, 4)<<0; //g1[3:0], - rgb[0][1] |= ReadBits(in, &bit, 6)<<10; //g0[10:15], + rgb[0][1] |=(ReadBits(in, &bit, 1)<<15) //g0[10:15], + | (ReadBits(in, &bit, 1)<<14) + | (ReadBits(in, &bit, 1)<<13) + | (ReadBits(in, &bit, 1)<<12) + | (ReadBits(in, &bit, 1)<<11) + | (ReadBits(in, &bit, 1)<<10); rgb[1][2] |= ReadBits(in, &bit, 4)<<0; //b1[3:0], - rgb[0][2] |= ReadBits(in, &bit, 6)<<10; //b0[10:15] + rgb[0][2] |=(ReadBits(in, &bit, 1)<<15) //b0[10:15] + | (ReadBits(in, &bit, 1)<<14) + | (ReadBits(in, &bit, 1)<<13) + | (ReadBits(in, &bit, 1)<<12) + | (ReadBits(in, &bit, 1)<<11) + | (ReadBits(in, &bit, 1)<<10); shapeindex = 0; break; @@ -7003,7 +7337,6 @@ static void Image_Decode_BC6_Block(qbyte *fte_restrict in, pixel64_t *fte_restri { for (i = 0; i < 16; ) { - // int pidx = p[i]; int idx; if (i == 0) idx = ReadBits(in, &bit, ib-1); @@ -7018,24 +7351,8 @@ static void Image_Decode_BC6_Block(qbyte *fte_restrict in, pixel64_t *fte_restri out += w-4; } } - if (bit != 128) - { - out -= 4*(w-4); //undo the above damage -// out->v[0] = 0;//0xf<<10; //must be 1 -// out->v[1] = 0;//0xf<<10; //must be 1 -// out->v[2] = 0;//0xf<<10; //must be 1 - out->v[3] = 0;//0xf<<10; //must be 1 - } } -static void Image_Decode_BC6S_Block(qbyte *fte_restrict in, pixel64_t *fte_restrict out, int w) -{ - Image_Decode_BC6_Block(in,out,w,true); -} -static void Image_Decode_BC6U_Block(qbyte *fte_restrict in, pixel64_t *fte_restrict out, int w) -{ - Image_Decode_BC6_Block(in,out,w,false); -} -static void Image_Decode_BC7_Block(qbyte *fte_restrict in, pixel32_t *fte_restrict out, int w) +static void Image_Decode_BC7_Block(qbyte *fte_restrict in, pixel32_t *fte_restrict out, int w, uploadfmt_t fmt) { static const qbyte p1[] = { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, @@ -7372,15 +7689,100 @@ static void Image_Decode_BC7_Block(qbyte *fte_restrict in, pixel32_t *fte_restri } #endif -static void Image_Decode_RGB8_Block(qbyte *fte_restrict in, pixel32_t *fte_restrict out, int w) +#ifdef DECOMPRESS_ASTC +#ifdef ASTC_WITH_LDR +static void Image_Decode_ASTC_LDR_U8_Block(qbyte *fte_restrict in, pixel32_t *fte_restrict out, int stride, uploadfmt_t fmt) +{ + int bw, bh, blockbytes; + Image_BlockSizeForEncoding(fmt, &blockbytes, &bw, &bh); + ASTC_Decode_LDR8(in, out->v, stride, bw, bh); +} +#endif +#ifdef ASTC_WITH_HDR +static void Image_Decode_ASTC_HDR_HF_Block(qbyte *fte_restrict in, pixel64_t *fte_restrict out, int stride, uploadfmt_t fmt) +{ + int bw, bh, blockbytes; + Image_BlockSizeForEncoding(fmt, &blockbytes, &bw, &bh); + ASTC_Decode_HDR(in, out->v, stride, bw, bh); +} + +static unsigned int RGB16F_to_E5BGR9(unsigned short Cr, unsigned short Cg, unsigned short Cb) +{ + int Re,Ge,Be, Rex,Gex,Bex, Xm, Xe; + uint32_t rshift, gshift, bshift, expo; + int Rm, Gm, Bm; + + if( Cr > 0x7c00 ) Cr = 0; else if( Cr == 0x7c00 ) Cr = 0x7bff; + if( Cg > 0x7c00 ) Cg = 0; else if( Cg == 0x7c00 ) Cg = 0x7bff; + if( Cb > 0x7c00 ) Cb = 0; else if( Cb == 0x7c00 ) Cb = 0x7bff; + Re = (Cr >> 10) & 0x1F; + Ge = (Cg >> 10) & 0x1F; + Be = (Cb >> 10) & 0x1F; + Rex = Re == 0 ? 1 : Re; + Gex = Ge == 0 ? 1 : Ge; + Bex = Be == 0 ? 1 : Be; + Xm = ((Cr | Cg | Cb) & 0x200) >> 9; + Xe = Re | Ge | Be; + + if (Xe == 0) + { + expo = rshift = gshift = bshift = Xm; + } + else if (Re >= Ge && Re >= Be) + { + expo = Rex + 1; + rshift = 2; + gshift = Rex - Gex + 2; + bshift = Rex - Bex + 2; + } + else if (Ge >= Be) + { + expo = Gex + 1; + rshift = Gex - Rex + 2; + gshift = 2; + bshift = Gex - Bex + 2; + } + else + { + expo = Bex + 1; + rshift = Bex - Rex + 2; + gshift = Bex - Gex + 2; + bshift = 2; + } + + Rm = (Cr & 0x3FF) | (Re == 0 ? 0 : 0x400); + Gm = (Cg & 0x3FF) | (Ge == 0 ? 0 : 0x400); + Bm = (Cb & 0x3FF) | (Be == 0 ? 0 : 0x400); + Rm = (Rm >> rshift) & 0x1FF; + Gm = (Gm >> gshift) & 0x1FF; + Bm = (Bm >> bshift) & 0x1FF; + + return (expo << 27) | (Bm << 18) | (Gm << 9) | (Rm << 0); +} +static void Image_Decode_ASTC_HDR_E5_Block(qbyte *fte_restrict in, pixel32_t *fte_restrict out, int stride, uploadfmt_t fmt) +{ + unsigned short hdr[12][12][4]; + int bw, bh, blockbytes; + int x, y; + Image_BlockSizeForEncoding(fmt, &blockbytes, &bw, &bh); + ASTC_Decode_HDR(in, hdr[0][0], 12, bw, bh); + + for (y = 0; y < bh; y++, out += stride) + for (x = 0; x < bw; x++) + out[x].u = RGB16F_to_E5BGR9(hdr[y][x][0], hdr[y][x][1], hdr[y][x][2]); +} +#endif +#endif + +static void Image_Decode_RGB8_Block(qbyte *fte_restrict in, pixel32_t *fte_restrict out, int w, uploadfmt_t srcfmt) { Vector4Set(out->v, in[0], in[1], in[2], 0xff); } -static void Image_Decode_L8A8_Block(qbyte *fte_restrict in, pixel32_t *fte_restrict out, int w) +static void Image_Decode_L8A8_Block(qbyte *fte_restrict in, pixel32_t *fte_restrict out, int w, uploadfmt_t srcfmt) { Vector4Set(out->v, in[0], in[0], in[0], in[1]); } -static void Image_Decode_L8_Block(qbyte *fte_restrict in, pixel32_t *fte_restrict out, int w) +static void Image_Decode_L8_Block(qbyte *fte_restrict in, pixel32_t *fte_restrict out, int w, uploadfmt_t srcfmt) { Vector4Set(out->v, in[0], in[0], in[0], 0xff); } @@ -7495,34 +7897,48 @@ void Image_BlockSizeForEncoding(uploadfmt_t encoding, unsigned int *blockbytes, break; // ASTC is crazy with its format subtypes... note that all are potentially rgba, selected on a per-block basis + case PTI_ASTC_4X4_HDR: case PTI_ASTC_4X4_SRGB: - case PTI_ASTC_4X4: w = 4; h = 4; b = 16; break; + case PTI_ASTC_4X4_LDR: w = 4; h = 4; b = 16; break; + case PTI_ASTC_5X4_HDR: case PTI_ASTC_5X4_SRGB: - case PTI_ASTC_5X4: w = 5; h = 4; b = 16; break; + case PTI_ASTC_5X4_LDR: w = 5; h = 4; b = 16; break; + case PTI_ASTC_5X5_HDR: case PTI_ASTC_5X5_SRGB: - case PTI_ASTC_5X5: w = 5; h = 5; b = 16; break; + case PTI_ASTC_5X5_LDR: w = 5; h = 5; b = 16; break; + case PTI_ASTC_6X5_HDR: case PTI_ASTC_6X5_SRGB: - case PTI_ASTC_6X5: w = 6; h = 5; b = 16; break; + case PTI_ASTC_6X5_LDR: w = 6; h = 5; b = 16; break; + case PTI_ASTC_6X6_HDR: case PTI_ASTC_6X6_SRGB: - case PTI_ASTC_6X6: w = 6; h = 6; b = 16; break; + case PTI_ASTC_6X6_LDR: w = 6; h = 6; b = 16; break; + case PTI_ASTC_8X5_HDR: case PTI_ASTC_8X5_SRGB: - case PTI_ASTC_8X5: w = 8; h = 5; b = 16; break; + case PTI_ASTC_8X5_LDR: w = 8; h = 5; b = 16; break; + case PTI_ASTC_8X6_HDR: case PTI_ASTC_8X6_SRGB: - case PTI_ASTC_8X6: w = 8; h = 6; b = 16; break; + case PTI_ASTC_8X6_LDR: w = 8; h = 6; b = 16; break; + case PTI_ASTC_10X5_HDR: case PTI_ASTC_10X5_SRGB: - case PTI_ASTC_10X5: w = 10; h = 5; b = 16; break; + case PTI_ASTC_10X5_LDR: w = 10; h = 5; b = 16; break; + case PTI_ASTC_10X6_HDR: case PTI_ASTC_10X6_SRGB: - case PTI_ASTC_10X6: w = 10; h = 6; b = 16; break; + case PTI_ASTC_10X6_LDR: w = 10; h = 6; b = 16; break; + case PTI_ASTC_8X8_HDR: case PTI_ASTC_8X8_SRGB: - case PTI_ASTC_8X8: w = 8; h = 8; b = 16; break; + case PTI_ASTC_8X8_LDR: w = 8; h = 8; b = 16; break; + case PTI_ASTC_10X8_HDR: case PTI_ASTC_10X8_SRGB: - case PTI_ASTC_10X8: w = 10; h = 8; b = 16; break; + case PTI_ASTC_10X8_LDR: w = 10; h = 8; b = 16; break; + case PTI_ASTC_10X10_HDR: case PTI_ASTC_10X10_SRGB: - case PTI_ASTC_10X10: w = 10; h = 10; b = 16; break; + case PTI_ASTC_10X10_LDR: w = 10; h = 10; b = 16; break; + case PTI_ASTC_12X10_HDR: case PTI_ASTC_12X10_SRGB: - case PTI_ASTC_12X10: w = 12; h = 10; b = 16; break; + case PTI_ASTC_12X10_LDR: w = 12; h = 10; b = 16; break; + case PTI_ASTC_12X12_HDR: case PTI_ASTC_12X12_SRGB: - case PTI_ASTC_12X12: w = 12; h = 12; b = 16; break; + case PTI_ASTC_12X12_LDR: w = 12; h = 12; b = 16; break; case PTI_EMULATED: #ifdef FTE_TARGET_WEB @@ -7604,34 +8020,48 @@ const char *Image_FormatName(uploadfmt_t fmt) case PTI_ETC2_RGB8A8_SRGB: return "ETC2_RGB8A8_SRGB"; case PTI_EAC_RG11: return "EAC_RG11"; case PTI_EAC_RG11_SNORM: return "EAC_RG11_SNORM"; + case PTI_ASTC_4X4_HDR: return "ASTC_4X4_HDR"; case PTI_ASTC_4X4_SRGB: return "ASTC_4X4_SRGB"; - case PTI_ASTC_4X4: return "ASTC_4X4"; + case PTI_ASTC_4X4_LDR: return "ASTC_4X4_LDR"; + case PTI_ASTC_5X4_HDR: return "ASTC_5X4_HDR"; case PTI_ASTC_5X4_SRGB: return "ASTC_5X4_SRGB"; - case PTI_ASTC_5X4: return "ASTC_5X4"; + case PTI_ASTC_5X4_LDR: return "ASTC_5X4_LDR"; + case PTI_ASTC_5X5_HDR: return "ASTC_5X5_HDR"; case PTI_ASTC_5X5_SRGB: return "ASTC_5X5_SRGB"; - case PTI_ASTC_5X5: return "ASTC_5X5"; + case PTI_ASTC_5X5_LDR: return "ASTC_5X5_LDR"; + case PTI_ASTC_6X5_HDR: return "ASTC_6X5_HDR"; case PTI_ASTC_6X5_SRGB: return "ASTC_6X5_SRGB"; - case PTI_ASTC_6X5: return "ASTC_6X5"; + case PTI_ASTC_6X5_LDR: return "ASTC_6X5_LDR"; + case PTI_ASTC_6X6_HDR: return "ASTC_6X6_HDR"; case PTI_ASTC_6X6_SRGB: return "ASTC_6X6_SRGB"; - case PTI_ASTC_6X6: return "ASTC_6X6"; + case PTI_ASTC_6X6_LDR: return "ASTC_6X6_LDR"; + case PTI_ASTC_8X5_HDR: return "ASTC_8X5_HDR"; case PTI_ASTC_8X5_SRGB: return "ASTC_8X5_SRGB"; - case PTI_ASTC_8X5: return "ASTC_8X5"; + case PTI_ASTC_8X5_LDR: return "ASTC_8X5_LDR"; + case PTI_ASTC_8X6_HDR: return "ASTC_8X6_HDR"; case PTI_ASTC_8X6_SRGB: return "ASTC_8X6_SRGB"; - case PTI_ASTC_8X6: return "ASTC_8X6"; + case PTI_ASTC_8X6_LDR: return "ASTC_8X6_LDR"; + case PTI_ASTC_10X5_HDR: return "ASTC_10X5_HDR"; case PTI_ASTC_10X5_SRGB: return "ASTC_10X5_SRGB"; - case PTI_ASTC_10X5: return "ASTC_10X5"; + case PTI_ASTC_10X5_LDR: return "ASTC_10X5_LDR"; + case PTI_ASTC_10X6_HDR: return "ASTC_10X6_HDR"; case PTI_ASTC_10X6_SRGB: return "ASTC_10X6_SRGB"; - case PTI_ASTC_10X6: return "ASTC_10X6"; + case PTI_ASTC_10X6_LDR: return "ASTC_10X6_LDR"; + case PTI_ASTC_8X8_HDR: return "ASTC_8X8_HDR"; case PTI_ASTC_8X8_SRGB: return "ASTC_8X8_SRGB"; - case PTI_ASTC_8X8: return "ASTC_8X8"; + case PTI_ASTC_8X8_LDR: return "ASTC_8X8_LDR"; + case PTI_ASTC_10X8_HDR: return "ASTC_10X8_HDR"; case PTI_ASTC_10X8_SRGB: return "ASTC_10X8_SRGB"; - case PTI_ASTC_10X8: return "ASTC_10X8"; + case PTI_ASTC_10X8_LDR: return "ASTC_10X8_LDR"; + case PTI_ASTC_10X10_HDR: return "ASTC_10X10_HDR"; case PTI_ASTC_10X10_SRGB: return "ASTC_10X10_SRGB"; - case PTI_ASTC_10X10: return "ASTC_10X10"; + case PTI_ASTC_10X10_LDR: return "ASTC_10X10_LDR"; + case PTI_ASTC_12X10_HDR: return "ASTC_12X10_HDR"; case PTI_ASTC_12X10_SRGB: return "ASTC_12X10_SRGB"; - case PTI_ASTC_12X10: return "ASTC_12X10"; + case PTI_ASTC_12X10_LDR: return "ASTC_12X10_LDR"; + case PTI_ASTC_12X12_HDR: return "ASTC_12X12_HDR"; case PTI_ASTC_12X12_SRGB: return "ASTC_12X12_SRGB"; - case PTI_ASTC_12X12: return "ASTC_12X12"; + case PTI_ASTC_12X12_LDR: return "ASTC_12X12_LDR"; #ifdef FTE_TARGET_WEB case PTI_WHOLEFILE: return "Whole File"; @@ -7643,13 +8073,14 @@ const char *Image_FormatName(uploadfmt_t fmt) return "Unknown"; } -static pixel32_t *Image_Block_Decode(qbyte *fte_restrict in, size_t insize, int w, int h, void(*decodeblock)(qbyte *fte_restrict in, pixel32_t *fte_restrict out, int w), uploadfmt_t encoding) +static pixel32_t *Image_Block_Decode(qbyte *fte_restrict in, size_t insize, int w, int h, void(*decodeblock)(qbyte *fte_restrict in, pixel32_t *fte_restrict out, int w, uploadfmt_t srcfmt), uploadfmt_t encoding) { #define TMPBLOCKSIZE 16u pixel32_t *ret, *out; pixel32_t tmp[TMPBLOCKSIZE*TMPBLOCKSIZE]; int x, y, i, j; int sizediff; + int rows, columns; unsigned int blockbytes, blockwidth, blockheight; Image_BlockSizeForEncoding(encoding, &blockbytes, &blockwidth, &blockheight); @@ -7667,13 +8098,17 @@ static pixel32_t *Image_Block_Decode(qbyte *fte_restrict in, size_t insize, int ret = out = BZ_Malloc(w*h*sizeof(*out)); - for (y = 0; y < (h&~(blockheight-1)); y+=blockheight, out += w*(blockheight-1)) + rows = h/blockheight; + rows *= blockheight; + columns = w/blockwidth; + columns *= blockwidth; + for (y = 0; y < rows; y+=blockheight, out += w*(blockheight-1)) { - for (x = 0; x < (w&~(blockwidth-1)); x+=blockwidth, in+=blockbytes, out+=blockwidth) - decodeblock(in, out, w); + for (x = 0; x < columns; x+=blockwidth, in+=blockbytes, out+=blockwidth) + decodeblock(in, out, w, encoding); if (w%blockwidth) { - decodeblock(in, tmp, TMPBLOCKSIZE); + decodeblock(in, tmp, TMPBLOCKSIZE, encoding); for (i = 0; x < w; x++, out++, i++) { for (j = 0; j < blockheight; j++) @@ -7687,7 +8122,7 @@ static pixel32_t *Image_Block_Decode(qbyte *fte_restrict in, size_t insize, int h %= blockheight; for (x = 0; x < w; ) { - decodeblock(in, tmp, TMPBLOCKSIZE); + decodeblock(in, tmp, TMPBLOCKSIZE, encoding); i = 0; do { @@ -7703,13 +8138,14 @@ static pixel32_t *Image_Block_Decode(qbyte *fte_restrict in, size_t insize, int } return ret; } -static pixel64_t *Image_Block_Decode64(qbyte *fte_restrict in, size_t insize, int w, int h, void(*decodeblock)(qbyte *fte_restrict in, pixel64_t *fte_restrict out, int w), uploadfmt_t encoding) +static pixel64_t *Image_Block_Decode64(qbyte *fte_restrict in, size_t insize, int w, int h, void(*decodeblock)(qbyte *fte_restrict in, pixel64_t *fte_restrict out, int w, uploadfmt_t srcfmt), uploadfmt_t encoding) { #define TMPBLOCKSIZE 16u pixel64_t *ret, *out; pixel64_t tmp[TMPBLOCKSIZE*TMPBLOCKSIZE]; int x, y, i, j; int sizediff; + int rows, columns; unsigned int blockbytes, blockwidth, blockheight; Image_BlockSizeForEncoding(encoding, &blockbytes, &blockwidth, &blockheight); @@ -7727,13 +8163,17 @@ static pixel64_t *Image_Block_Decode64(qbyte *fte_restrict in, size_t insize, in ret = out = BZ_Malloc(w*h*sizeof(*out)); - for (y = 0; y < (h&~(blockheight-1)); y+=blockheight, out += w*(blockheight-1)) + rows = h/blockheight; + rows *= blockheight; + columns = w/blockwidth; + columns *= blockwidth; + for (y = 0; y < rows; y+=blockheight, out += w*(blockheight-1)) { - for (x = 0; x < (w&~(blockwidth-1)); x+=blockwidth, in+=blockbytes, out+=blockwidth) - decodeblock(in, out, w); + for (x = 0; x < columns; x+=blockwidth, in+=blockbytes, out+=blockwidth) + decodeblock(in, out, w, encoding); if (w%blockwidth) { - decodeblock(in, tmp, TMPBLOCKSIZE); + decodeblock(in, tmp, TMPBLOCKSIZE, encoding); for (i = 0; x < w; x++, out++, i++) { for (j = 0; j < blockheight; j++) @@ -7747,7 +8187,7 @@ static pixel64_t *Image_Block_Decode64(qbyte *fte_restrict in, size_t insize, in h %= blockheight; for (x = 0; x < w; ) { - decodeblock(in, tmp, TMPBLOCKSIZE); + decodeblock(in, tmp, TMPBLOCKSIZE, encoding); i = 0; do { @@ -7764,7 +8204,7 @@ static pixel64_t *Image_Block_Decode64(qbyte *fte_restrict in, size_t insize, in return ret; } -static void Image_DecompressFormat(struct pendingtextureinfo *mips) +static qboolean Image_DecompressFormat(struct pendingtextureinfo *mips, const char *imagename) { //various compressed formats might not be supported by various gpus/apis. //sometimes the gpu might only partially support the format (eg: d3d requires mip 0 be a multiple of the block size) @@ -7774,8 +8214,8 @@ static void Image_DecompressFormat(struct pendingtextureinfo *mips) //iiuc any basic s3tc patents have now expired, so it is legally safe to decode (though fancy compression logic may still have restrictions, but we don't compress). static float throttle; - void (*decodefunc)(qbyte *fte_restrict, pixel32_t *fte_restrict, int) = NULL; - void (*decodefunc64)(qbyte *fte_restrict, pixel64_t *fte_restrict, int) = NULL; + void (*decodefunc)(qbyte *fte_restrict, pixel32_t *fte_restrict, int, uploadfmt_t) = NULL; + void (*decodefunc64)(qbyte *fte_restrict, pixel64_t *fte_restrict, int, uploadfmt_t) = NULL; int rcoding = mips->encoding; int mip; switch(mips->encoding) @@ -7876,24 +8316,18 @@ static void Image_DecompressFormat(struct pendingtextureinfo *mips) decodefunc = Image_Decode_BC3_Block; rcoding = (mips->encoding==PTI_BC3_RGBA_SRGB)?PTI_RGBA8_SRGB:PTI_RGBA8; #else - Con_ThrottlePrintf(&throttle, 0, "BC3 decompression is not supported in this build\n"); + Con_ThrottlePrintf(&throttle, 0, "Fallback BC3 decompression is not supported in this build\n"); #endif break; #ifdef DECOMPRESS_RGTC case PTI_BC4_R8_SNORM: - decodefunc = Image_Decode_BC4S_Block; - rcoding = PTI_RGBX8; - break; case PTI_BC4_R8: - decodefunc = Image_Decode_BC4U_Block; + decodefunc = Image_Decode_BC4_Block; rcoding = PTI_RGBX8; break; case PTI_BC5_RG8_SNORM: - decodefunc = Image_Decode_BC5S_Block; - rcoding = PTI_RGBX8; - break; case PTI_BC5_RG8: - decodefunc = Image_Decode_BC5U_Block; + decodefunc = Image_Decode_BC5_Block; rcoding = PTI_RGBX8; break; #else @@ -7901,23 +8335,23 @@ static void Image_DecompressFormat(struct pendingtextureinfo *mips) case PTI_BC4_R8: case PTI_BC5_RG8_SNORM: case PTI_BC5_RG8: - Con_ThrottlePrintf(&throttle, 0, "BC4/BC5 decompression is not supported in this build\n"); + Con_ThrottlePrintf(&throttle, 0, "Fallback BC4/BC5 decompression is not supported in this build\n"); break; #endif case PTI_BC6_RGB_UFLOAT: #ifdef DECOMPRESS_BPTC - decodefunc64 = Image_Decode_BC6U_Block; + decodefunc64 = Image_Decode_BC6_Block; rcoding = PTI_RGBA16F; #else - Con_ThrottlePrintf(&throttle, 0, "BC6_UFLOAT decompression is not supported\n"); + Con_ThrottlePrintf(&throttle, 0, "Fallback BC6_UFLOAT decompression is not supported\n"); #endif break; case PTI_BC6_RGB_SFLOAT: #ifdef DECOMPRESS_BPTC - decodefunc64 = Image_Decode_BC6S_Block; + decodefunc64 = Image_Decode_BC6_Block; rcoding = PTI_RGBA16F; #else - Con_ThrottlePrintf(&throttle, 0, "BC6_SFLOAT decompression is not supported\n"); + Con_ThrottlePrintf(&throttle, 0, "Fallback BC6_SFLOAT decompression is not supported\n"); #endif break; case PTI_BC7_RGBA: @@ -7926,7 +8360,75 @@ static void Image_DecompressFormat(struct pendingtextureinfo *mips) decodefunc = Image_Decode_BC7_Block; rcoding = (mips->encoding==PTI_BC7_RGBA_SRGB)?PTI_RGBA8_SRGB:PTI_RGBA8; #else - Con_ThrottlePrintf(&throttle, 0, "BC7 decompression is not supported\n"); + Con_ThrottlePrintf(&throttle, 0, "Fallback BC7 decompression is not supported\n"); +#endif + break; + + case PTI_ASTC_4X4_HDR: + case PTI_ASTC_5X4_HDR: + case PTI_ASTC_5X5_HDR: + case PTI_ASTC_6X5_HDR: + case PTI_ASTC_6X6_HDR: + case PTI_ASTC_8X5_HDR: + case PTI_ASTC_8X6_HDR: + case PTI_ASTC_10X5_HDR: + case PTI_ASTC_10X6_HDR: + case PTI_ASTC_8X8_HDR: + case PTI_ASTC_10X8_HDR: + case PTI_ASTC_10X10_HDR: + case PTI_ASTC_12X10_HDR: + case PTI_ASTC_12X12_HDR: +#if defined(DECOMPRESS_ASTC) && defined(ASTC_WITH_HDR) + decodefunc = Image_Decode_ASTC_HDR_E5_Block; + rcoding = PTI_E5BGR9; + + decodefunc64 = Image_Decode_ASTC_HDR_HF_Block; + rcoding = PTI_RGBA16F; + break; +#endif + case PTI_ASTC_4X4_LDR: + case PTI_ASTC_5X4_LDR: + case PTI_ASTC_5X5_LDR: + case PTI_ASTC_6X5_LDR: + case PTI_ASTC_6X6_LDR: + case PTI_ASTC_8X5_LDR: + case PTI_ASTC_8X6_LDR: + case PTI_ASTC_10X5_LDR: + case PTI_ASTC_10X6_LDR: + case PTI_ASTC_8X8_LDR: + case PTI_ASTC_10X8_LDR: + case PTI_ASTC_10X10_LDR: + case PTI_ASTC_12X10_LDR: + case PTI_ASTC_12X12_LDR: +#ifdef DECOMPRESS_ASTC +#ifdef ASTC_WITH_LDR + decodefunc = Image_Decode_ASTC_LDR_U8_Block; + rcoding = PTI_RGBA8; +#else + decodefunc64 = Image_Decode_ASTC_HDR_HF_Block; + rcoding = PTI_RGBA16F; +#endif + break; +#endif + case PTI_ASTC_4X4_SRGB: + case PTI_ASTC_5X4_SRGB: + case PTI_ASTC_5X5_SRGB: + case PTI_ASTC_6X5_SRGB: + case PTI_ASTC_6X6_SRGB: + case PTI_ASTC_8X5_SRGB: + case PTI_ASTC_8X6_SRGB: + case PTI_ASTC_10X5_SRGB: + case PTI_ASTC_10X6_SRGB: + case PTI_ASTC_8X8_SRGB: + case PTI_ASTC_10X8_SRGB: + case PTI_ASTC_10X10_SRGB: + case PTI_ASTC_12X10_SRGB: + case PTI_ASTC_12X12_SRGB: +#if defined(DECOMPRESS_ASTC) && defined(ASTC_WITH_LDR) + decodefunc = Image_Decode_ASTC_LDR_U8_Block; + rcoding = PTI_RGBA8_SRGB; +#else + Con_ThrottlePrintf(&throttle, 0, "Fallback ASTC decompression is not supported\n"); #endif break; case PTI_INVALID: @@ -7935,6 +8437,8 @@ static void Image_DecompressFormat(struct pendingtextureinfo *mips) } if (decodefunc || decodefunc64) { + if (imagename) + Con_DPrintf("Software-decoding %s (%s)\r", imagename, Image_FormatName(mips->encoding)); for (mip = 0; mip < mips->mipcount; mip++) { size_t sz; @@ -7959,10 +8463,12 @@ static void Image_DecompressFormat(struct pendingtextureinfo *mips) BZ_Free(mips->extrafree); //might as well free this now, as nothing is poking it any more. mips->extrafree = NULL; mips->encoding = rcoding; + return true; } + return false; } -static void Image_ChangeFormat(struct pendingtextureinfo *mips, unsigned int flags, uploadfmt_t origfmt) +static void Image_ChangeFormat(struct pendingtextureinfo *mips, unsigned int flags, uploadfmt_t origfmt, const char *imagename) { int mip; @@ -7971,7 +8477,7 @@ static void Image_ChangeFormat(struct pendingtextureinfo *mips, unsigned int fla if (flags & IF_PALETTIZE) { - Image_DecompressFormat(mips); //force-decompress it, so that we can palettise it. + Image_DecompressFormat(mips, NULL); //force-decompress it, so that we can palettise it. if (mips->encoding == PTI_RGBX8 || mips->encoding == PTI_RGBA8) { mips->encoding = PTI_P8; @@ -8006,10 +8512,12 @@ static void Image_ChangeFormat(struct pendingtextureinfo *mips, unsigned int fla //if that format isn't supported/desired, try converting it. if (sh_config.texfmt[mips->encoding]) { - if (!sh_config.texture_allow_block_padding && mips->mipcount) + if (mips->encoding >= PTI_ASTC_FIRST && mips->encoding <= PTI_ASTC_LAST) + return; //ignore texture_allow_block_padding for astc. + else if (!sh_config.texture_allow_block_padding && mips->mipcount && mips->encoding) { //direct3d is annoying, and will reject any block-compressed format with a base mip size that is not a multiple of the block size. //its fine with weirdly sized mips though. I have no idea why there's this restriction, but whatever. - //we need to de + //we need to manually decompress in order to correctly handle such images int blockbytes, blockwidth, blockheight; Image_BlockSizeForEncoding(mips->encoding, &blockbytes, &blockwidth, &blockheight); if (!(mips->mip[0].width % blockwidth) && !(mips->mip[0].height % blockheight)) @@ -8021,7 +8529,7 @@ static void Image_ChangeFormat(struct pendingtextureinfo *mips, unsigned int fla } //when the format can't be used, decompress it if its one of those awkward compressed formats. - Image_DecompressFormat(mips); + Image_DecompressFormat(mips, imagename); if (sh_config.texfmt[mips->encoding]) return; //okay, that got it. @@ -8573,34 +9081,48 @@ static qboolean Image_GenMip0(struct pendingtextureinfo *mips, unsigned int flag case PTI_ETC2_RGB8A1_SRGB: //would need to force the 'opaque' bit in each block and treat as PTI_ETC2_RGB8. case PTI_ETC2_RGB8A8: //could strip to PTI_ETC2_RGB8 case PTI_ETC2_RGB8A8_SRGB: //could strip to PTI_ETC2_SRGB8 - case PTI_ASTC_4X4: + case PTI_ASTC_4X4_LDR: case PTI_ASTC_4X4_SRGB: - case PTI_ASTC_5X4: + case PTI_ASTC_4X4_HDR: + case PTI_ASTC_5X4_LDR: case PTI_ASTC_5X4_SRGB: - case PTI_ASTC_5X5: + case PTI_ASTC_5X4_HDR: + case PTI_ASTC_5X5_LDR: case PTI_ASTC_5X5_SRGB: - case PTI_ASTC_6X5: + case PTI_ASTC_5X5_HDR: + case PTI_ASTC_6X5_LDR: case PTI_ASTC_6X5_SRGB: - case PTI_ASTC_6X6: + case PTI_ASTC_6X5_HDR: + case PTI_ASTC_6X6_LDR: case PTI_ASTC_6X6_SRGB: - case PTI_ASTC_8X5: + case PTI_ASTC_6X6_HDR: + case PTI_ASTC_8X5_LDR: case PTI_ASTC_8X5_SRGB: - case PTI_ASTC_8X6: + case PTI_ASTC_8X5_HDR: + case PTI_ASTC_8X6_LDR: case PTI_ASTC_8X6_SRGB: - case PTI_ASTC_10X5: + case PTI_ASTC_8X6_HDR: + case PTI_ASTC_10X5_LDR: case PTI_ASTC_10X5_SRGB: - case PTI_ASTC_10X6: + case PTI_ASTC_10X5_HDR: + case PTI_ASTC_10X6_LDR: case PTI_ASTC_10X6_SRGB: - case PTI_ASTC_8X8: + case PTI_ASTC_10X6_HDR: + case PTI_ASTC_8X8_LDR: case PTI_ASTC_8X8_SRGB: - case PTI_ASTC_10X8: + case PTI_ASTC_8X8_HDR: + case PTI_ASTC_10X8_LDR: case PTI_ASTC_10X8_SRGB: - case PTI_ASTC_10X10: + case PTI_ASTC_10X8_HDR: + case PTI_ASTC_10X10_LDR: case PTI_ASTC_10X10_SRGB: - case PTI_ASTC_12X10: + case PTI_ASTC_10X10_HDR: + case PTI_ASTC_12X10_LDR: case PTI_ASTC_12X10_SRGB: - case PTI_ASTC_12X12: + case PTI_ASTC_12X10_HDR: + case PTI_ASTC_12X12_LDR: case PTI_ASTC_12X12_SRGB: + case PTI_ASTC_12X12_HDR: #ifdef FTE_TARGET_WEB case PTI_WHOLEFILE: #endif @@ -8674,20 +9196,20 @@ static qboolean Image_GenMip0(struct pendingtextureinfo *mips, unsigned int flag case PTI_ETC2_RGB8: nf = PTI_ETC2_RGB8_SRGB; break; case PTI_ETC2_RGB8A1: nf = PTI_ETC2_RGB8A1_SRGB; break; case PTI_ETC2_RGB8A8: nf = PTI_ETC2_RGB8A8_SRGB; break; - case PTI_ASTC_4X4: nf = PTI_ASTC_4X4_SRGB; break; - case PTI_ASTC_5X4: nf = PTI_ASTC_5X4_SRGB; break; - case PTI_ASTC_5X5: nf = PTI_ASTC_5X5_SRGB; break; - case PTI_ASTC_6X5: nf = PTI_ASTC_6X5_SRGB; break; - case PTI_ASTC_6X6: nf = PTI_ASTC_6X6_SRGB; break; - case PTI_ASTC_8X5: nf = PTI_ASTC_8X5_SRGB; break; - case PTI_ASTC_8X6: nf = PTI_ASTC_8X6_SRGB; break; - case PTI_ASTC_10X5: nf = PTI_ASTC_10X5_SRGB; break; - case PTI_ASTC_10X6: nf = PTI_ASTC_10X6_SRGB; break; - case PTI_ASTC_8X8: nf = PTI_ASTC_8X8_SRGB; break; - case PTI_ASTC_10X8: nf = PTI_ASTC_10X8_SRGB; break; - case PTI_ASTC_10X10: nf = PTI_ASTC_10X10_SRGB; break; - case PTI_ASTC_12X10: nf = PTI_ASTC_12X10_SRGB; break; - case PTI_ASTC_12X12: nf = PTI_ASTC_12X12_SRGB; break; + case PTI_ASTC_4X4_LDR: nf = PTI_ASTC_4X4_SRGB; break; + case PTI_ASTC_5X4_LDR: nf = PTI_ASTC_5X4_SRGB; break; + case PTI_ASTC_5X5_LDR: nf = PTI_ASTC_5X5_SRGB; break; + case PTI_ASTC_6X5_LDR: nf = PTI_ASTC_6X5_SRGB; break; + case PTI_ASTC_6X6_LDR: nf = PTI_ASTC_6X6_SRGB; break; + case PTI_ASTC_8X5_LDR: nf = PTI_ASTC_8X5_SRGB; break; + case PTI_ASTC_8X6_LDR: nf = PTI_ASTC_8X6_SRGB; break; + case PTI_ASTC_10X5_LDR: nf = PTI_ASTC_10X5_SRGB; break; + case PTI_ASTC_10X6_LDR: nf = PTI_ASTC_10X6_SRGB; break; + case PTI_ASTC_8X8_LDR: nf = PTI_ASTC_8X8_SRGB; break; + case PTI_ASTC_10X8_LDR: nf = PTI_ASTC_10X8_SRGB; break; + case PTI_ASTC_10X10_LDR:nf = PTI_ASTC_10X10_SRGB; break; + case PTI_ASTC_12X10_LDR:nf = PTI_ASTC_12X10_SRGB; break; + case PTI_ASTC_12X12_LDR:nf = PTI_ASTC_12X12_SRGB; break; default: if (freedata) BZ_Free(rgbadata); @@ -8886,7 +9408,7 @@ static qboolean Image_LoadRawTexture(texid_t tex, unsigned int flags, void *rawd return false; } Image_GenerateMips(mips, flags); - Image_ChangeFormat(mips, flags, fmt); + Image_ChangeFormat(mips, flags, fmt, tex->ident); tex->width = imgwidth; tex->height = imgheight; @@ -8930,6 +9452,10 @@ static struct pendingtextureinfo *Image_LoadMipsFromMemory(int flags, const char if (!mips && filedata[0] == 'V' && filedata[1] == 'T' && filedata[2] == 'F' && filedata[3] == '\0') mips = Image_ReadVTFFile(flags, fname, filedata, filesize); #endif +#ifdef IMAGEFMT_ASTC + if (!mips && filesize>= 16 && filedata[0] == 0x13 && filedata[1] == 0xab && filedata[2] == 0xa1 && filedata[3] == 0x5c) + mips = Image_ReadASTCFile(flags, fname, filedata, filesize); +#endif //the above formats are assumed to have consumed filedata somehow (probably storing into mips->extradata) if (mips) @@ -8944,7 +9470,7 @@ static struct pendingtextureinfo *Image_LoadMipsFromMemory(int flags, const char memmove(mips->mip, mips->mip+i, sizeof(*mips->mip)*mips->mipcount); } - Image_ChangeFormat(mips, flags, TF_INVALID); + Image_ChangeFormat(mips, flags, TF_INVALID, fname); return mips; } @@ -9019,7 +9545,7 @@ static struct pendingtextureinfo *Image_LoadMipsFromMemory(int flags, const char if (Image_GenMip0(mips, flags, rgbadata, NULL, imgwidth, imgheight, format, true)) { Image_GenerateMips(mips, flags); - Image_ChangeFormat(mips, flags, format); + Image_ChangeFormat(mips, flags, format, fname); BZ_Free(filedata); return mips; } @@ -9891,7 +10417,7 @@ void Image_Upload (texid_t tex, uploadfmt_t fmt, void *data, void *palette, in if (!Image_GenMip0(&mips, flags, data, palette, width, height, fmt, false)) return; Image_GenerateMips(&mips, flags); - Image_ChangeFormat(&mips, flags, fmt); + Image_ChangeFormat(&mips, flags, fmt, tex->ident); rf->IMG_LoadTextureMips(tex, &mips); tex->format = fmt; tex->width = width; @@ -10059,10 +10585,11 @@ void Image_List_f(void) failed++; continue; } + Con_Printf("^[\\imgptr\\%#"PRIxSIZE"^]", (size_t)tex); if (tex->subpath) Con_Printf("^h(%s)^h", tex->subpath); Con_DLPrintf(1, " %x", tex->flags); - + if (Image_LocateHighResTexture(tex, &loc, fname, sizeof(fname), &loadflags)) { char defuck[MAX_OSPATH], *bullshit; @@ -10128,6 +10655,8 @@ void Image_List_f(void) void Image_Formats_f(void) { size_t i; + float bpp; + int blockbytes, blockwidth, blockheight; #ifdef GLQUAKE if (qrenderer == QR_OPENGL) @@ -10181,7 +10710,9 @@ void Image_Formats_f(void) default: break; } - Con_Printf("%20s: %s\n", Image_FormatName(i), sh_config.texfmt[i]?S_COLOR_GREEN"Enabled":S_COLOR_RED"Disabled"); + Image_BlockSizeForEncoding(i, &blockbytes, &blockwidth, &blockheight); + bpp = blockbytes*8.0/(blockwidth*blockheight); + Con_Printf("%20s: %s"S_COLOR_GRAY" (%.3g-bpp)\n", Image_FormatName(i), sh_config.texfmt[i]?S_COLOR_GREEN"Enabled":S_COLOR_RED"Disabled", bpp); } } diff --git a/engine/client/image_astc.h b/engine/client/image_astc.h new file mode 100644 index 000000000..0b6d14c50 --- /dev/null +++ b/engine/client/image_astc.h @@ -0,0 +1,1567 @@ +//Note: this code does not claim to be bit-correct. +//It doesn't support volume textures. +//It doesn't validate block extents (and is generally unaware of more than one block anyway) +//It doesn't implement all validation checks, either. +//Do NOT use this code to validate any encoders... + +#ifndef ASTC_PUBLIC +#define ASTC_PUBLIC +#endif + +#define ASTC_WITH_LDR //comment out this line to disable pure-LDR decoding (the hdr code can still be used). +#define ASTC_WITH_HDR //comment out this line to disable HDR decoding. +#define ASTC_WITH_HDRTEST //comment out this line to disable HDR decoding. + +#ifdef ASTC_WITH_LDR + ASTC_PUBLIC void ASTC_Decode_LDR8(unsigned char *in, unsigned char *out, int pixstride, int bw,int bh); //generates RGBA8 data (gives error colour for hdr blocks!) +#endif +#ifdef ASTC_WITH_HDR + ASTC_PUBLIC void ASTC_Decode_HDR(unsigned char *in, unsigned short *out, int pixstride, int bw,int bh); //generates RGBA16F data. +#endif +#ifdef ASTC_WITH_HDRTEST + ASTC_PUBLIC int ASTC_BlocksAreHDR(unsigned char *in, size_t datasize, int bw, int bh, int bd); //returns true if n consecutive blocks require the HDR profile. +#endif + + + +#include +#include +#include +#ifndef Vector4Set + #define Vector4Set(r,x,y,z,w) {(r)[0] = x; (r)[1] = y;(r)[2] = z;(r)[3]=w;} +#endif +#ifndef countof + #define countof(array) (sizeof(array)/sizeof(array[0])) +#endif +#if defined(ASTC_WITH_LDR) || defined(ASTC_WITH_HDR) + #define ASTC_WITH_DECODE +#endif +enum +{ + ASTC_OKAY, + ASTC_ERROR, //validation errors + ASTC_UNSUPPORTED_FULL, //volume textures... Note: non-hdr profile errors are per-partition, so not an actual block error. + ASTC_RESERVED, //reserved bits. basically an error but might not be in the future. + ASTC_VOID_LDR, //not an error - the block is a single LDR colour, with an RGBA16 colour in the last 8 bytes. + ASTC_VOID_HDR //not an error - the block is a single HDR colour, with an RGBA16F colour in the last 8 bytes. +}; +struct astc_block_info +{ + unsigned char *in; //the 16 bytes of the block + char blocksize[3]; + + char status; //0=regular block, -1=error, etc + unsigned char dualplane; //two sets of weights instead of one. + unsigned char ccs; //second set applies to this component + + unsigned char precision; //defines the precision of the weights + + int wcount[4]; //x,y,z,total weight counts + int weight_bits; //size of weights section. + int config_bits; //size of header before the endpoint bits + int ep_bits; //size available to endpoints + unsigned char weights[64]; //official limit to the number of weights stored + + unsigned char partitions; //number of active partitions to select from (and number of endpoints to read) + unsigned short partindex; //used for deciding which partition each pixel belongs in + struct astc_part + { + char mode; //endpoint modes +#ifdef ASTC_WITH_HDR + char hdr; //endpoint colour mode - &1=rgb, &2=alpha +#endif + int ep[2][4]; + } part[4]; +}; + +static unsigned char ASTC_readbits(unsigned char *in, unsigned int offset, unsigned int count) +{ //only reads up to 9 bits, because offset 7 with 10 bits needs to read more than two bytes + unsigned short s; + in += offset>>3; + offset &= 7; + s = in[0]; + if (offset+count>8) + s |= (in[1]<<8); + s>>=offset; + return s & ((1u< 8) + { + count -= 8; + r |= ASTC_readbits(in, offset+count, 8)<32 is +1 (otherwise it would be 0-63) +//high bits are folded over +static unsigned char dequant_weight_1b[1<<1] = {0x00,0x40}; +static unsigned char dequant_weight_2b[1<<2] = {0x00,0x15,0x2b,0x40}; +static unsigned char dequant_weight_3b[1<<3] = {0x00,0x09,0x12,0x1b,0x25,0x2e,0x37,0x40}; +static unsigned char dequant_weight_4b[1<<4] = {0x00,0x04,0x08,0x0c,0x11,0x15,0x19,0x1d,0x23,0x27,0x2b,0x2f,0x34,0x38,0x3c,0x40}; +static unsigned char dequant_weight_5b[1<<5] = {0x00,0x02,0x04,0x06,0x08,0x0a,0x0c,0x0e,0x10,0x12,0x14,0x16,0x18,0x1a,0x1c,0x1e,0x22,0x24,0x26,0x28,0x2a,0x2c,0x2e,0x30,0x32,0x34,0x36,0x38,0x3a,0x3c,0x3e,0x40}; +static unsigned char dequant_weight_0t[3] = {0,32,64}; +static unsigned char dequant_weight_1t[6] = {0x00,0x40,0x0c,0x34,0x19,0x27}; +static unsigned char dequant_weight_2t[12] = {0x00,0x40,0x11,0x2f,0x06,0x3a,0x17,0x29,0x0c,0x34,0x1d,0x23}; +static unsigned char dequant_weight_3t[24] = {0x00,0x40,0x08,0x38,0x10,0x30,0x18,0x28,0x02,0x3e,0x0b,0x35,0x13,0x2d,0x1b,0x25,0x05,0x3b,0x0d,0x33,0x16,0x2a,0x1e,0x22}; +static unsigned char dequant_weight_0q[5] = {0,16,32,48,64}; +static unsigned char dequant_weight_1q[10] = {0x00,0x40,0x05,0x3b,0x0b,0x35,0x11,0x2f,0x17,0x29}; +static unsigned char dequant_weight_2q[20] = {0x00,0x40,0x10,0x30,0x03,0x3d,0x13,0x2d,0x06,0x3a,0x17,0x29,0x09,0x37,0x1a,0x26,0x0d,0x33,0x1d,0x23}; +static const struct +{ + unsigned char extra, bits, *dequant; +} astc_weightmode[] = +{ + {0,0, NULL}, //invalid + {0,0, NULL}, //invalid + {0,1, dequant_weight_1b}, //2 + {1,0, dequant_weight_0t}, //3 + {0,2, dequant_weight_2b}, //4 + {2,0, dequant_weight_0q}, //5 + {1,1, dequant_weight_1t}, //6 + {0,3, dequant_weight_3b}, //8 + {0,0, NULL}, //invalid + {0,0, NULL}, //invalid + {2,1, dequant_weight_1q}, //10 + {1,2, dequant_weight_2t}, //12 + {0,4, dequant_weight_4b}, //16 + {2,2, dequant_weight_2q}, //20 + {1,3, dequant_weight_3t}, //24 + {0,5, dequant_weight_5b}, //32 +}; +static unsigned int ASTC_DecodeSize(unsigned int count, unsigned int bits, unsigned char extra) +{ + return ((extra==1)?((count*8)+4)/5:0) + + ((extra==2)?((count*7)+2)/3:0) + + count*bits; +} + + +static void ASTC_ReadBlockMode(struct astc_block_info *b) +{ + unsigned char *in = b->in; + unsigned short s = ASTC_readmanybits(in, 0, 13);//in[0] | (in[1]<<8); + b->config_bits = 13; + + if ((s&0x1ff)==0x1fc) + { //void extent + if (s&0x200) + b->status = ASTC_VOID_HDR; + else + b->status = ASTC_VOID_LDR; + b->dualplane = b->precision = b->wcount[0] = b->wcount[1] = b->wcount[2] = b->partitions = 0; + return; + } + b->status = ASTC_OKAY; + b->dualplane = (s>>10)&1; //Dp + b->precision = (s>>(9-3))&(1<<3);//P + b->precision |= (s>>4)&1; //p0 + if (b->blocksize[2] != 1) + { //3d blocks have a different layout + b->status = ASTC_UNSUPPORTED_FULL; + } + else + { + b->wcount[2] = 1; + if (s&3) + { //one of the first 5 layouts... + b->precision|=(s&3)<<1; //p2, p1 + if (!(s&8)) + { //first two layouts... + if (!(s&4)) + { //layout0 + b->wcount[0] = ((s>>7)&3)+4; + b->wcount[1] = ((s>>5)&3)+2; + } + else + { //layout1 + b->wcount[0] = ((s>>7)&3)+8; + b->wcount[1] = ((s>>5)&3)+2; + } + } + else if (!(s&4)) + { //layout2 + b->wcount[0] = ((s>>5)&3)+2; + b->wcount[1] = ((s>>7)&3)+8; + } + else if (!(s&256)) + { //layout3 + b->wcount[0] = ((s>>5)&3)+2; + b->wcount[1] = ((s>>7)&1)+6; + } + else + { //layout4 + b->wcount[0] = ((s>>7)&1)+2; + b->wcount[1] = ((s>>5)&3)+2; + } + } + else + { //one of the later layouts + b->precision|=(s&0xc)>>1; //p2, p1 + if (!(s&384)) + { + b->wcount[0] = 12; + b->wcount[1] = ((s>>5)&3)+2; + } + else if ((s&384)==128) + { + b->wcount[0] = ((s>>5)&3)+2; + b->wcount[1] = 12; + } + else if ((s&480)==384) + { + b->wcount[0] = 6; + b->wcount[1] = 10; + } + else if ((s&480)==416) + { + b->wcount[0] = 10; + b->wcount[1] = 6; + } + else if ((s&384)==256) + { + b->wcount[0] = ((s>>5)&3)+6; + b->wcount[1] = ((s>>9)&3)+6; + b->dualplane = 0; //forget the Dp bit, its reused in this layout + b->precision &= 7; //forget the P bit, too + } + else + b->status = ASTC_RESERVED; //reserved + } + } + b->partitions = ((s>>11)&3)+1; + + if (b->partitions > 3 && b->dualplane) + b->status = ASTC_ERROR; //apparently. + + if (b->wcount[0] > b->blocksize[0] || b->wcount[1] > b->blocksize[1] || b->wcount[2] > b->blocksize[2]) + b->status = ASTC_ERROR; //invalid weight counts. + + b->wcount[3] = b->wcount[0] * b->wcount[1] * b->wcount[2]; + b->wcount[3]<<=b->dualplane; //dual-plane has twice the weights - interleaved. + if (b->wcount[3] > countof(b->weights)) + b->status = ASTC_ERROR; //more than 64 weights are banned, for some reason + b->weight_bits = ASTC_DecodeSize(b->wcount[3], astc_weightmode[b->precision].bits, astc_weightmode[b->precision].extra); +} + +static void ASTC_ReadPartitions(struct astc_block_info *b) +{ + int sel; + int i; + unsigned char *in = b->in; + int weight_bits = b->weight_bits; + + if (b->partitions == 1) + { //single-partition mode, simple CEM + b->partindex = 0; + b->part[0].mode = ASTC_readbits(in, b->config_bits, 4); + b->config_bits += 4; + } + else + { //multi + b->partindex = ASTC_readmanybits(in, b->config_bits, 10); + b->config_bits += 10; + sel = ASTC_readbits(in, b->config_bits, 6); + b->config_bits += 6; + if (!(sel&3)) + { + sel = (sel>>2)&0xf; + for (i = 0; i < b->partitions; i++) + b->part[i].mode = sel; //all the same + } + else + { + int shift = 2; + int highbits = b->partitions*3 - 4; + + weight_bits += highbits; + sel |= ASTC_readbits(in, 128-weight_bits, highbits)<<6; //I don't know why this is separate. it seems like an unnecessary complication to me. + + for (i = 0; i < b->partitions; i++, shift++) + { + b->part[i].mode = ((sel&3)-1)<<2; //class groups + b->part[i].mode += ((sel>>shift)&1)<<2;//class + } + for (i = 0; i < b->partitions; i++, shift+=2) + b->part[i].mode += (sel>>shift)&3; //specific mode info + } + } + if (b->dualplane) + { + weight_bits += 2; + b->ccs = ASTC_readbits(in, 128-weight_bits, 2); + } + else + b->ccs = 0; + + b->ep_bits = 128 - weight_bits - b->config_bits; + //weights are at 128-weight_bits to 128 + //epdata is at config_bits to config_bits+ep_bits +} + +#ifdef ASTC_WITH_HDRTEST +ASTC_PUBLIC int ASTC_BlocksAreHDR(unsigned char *in, size_t datasize, int bw, int bh, int bd) +{ + struct astc_block_info b; + int i; + size_t blocks = datasize/16; + b.in = in; + b.blocksize[0] = bw; + b.blocksize[1] = bh; + b.blocksize[2] = bd; + while(blocks --> 0) + { + ASTC_ReadBlockMode(&b); + if (b.status == ASTC_VOID_HDR) + return 1; //if we're getting hdr blocks then we can decode properly only with hdr + if (b.status == ASTC_VOID_LDR) + return 0; //if we're getting ldr blocks, then its unlikely that there's any hdr blocks in there. + if (b.status != ASTC_OKAY) + continue; + ASTC_ReadPartitions(&b); + for (i = 0; i < b.partitions; i++) + { + switch(b.part[i].mode) + { + case 2: + case 3: + case 7: + case 11: + case 14: + case 15: + return 1; + } + } + b.in += 16; + } + return 0; +} +#endif + +#ifdef ASTC_WITH_DECODE +static unsigned char ASTC_readbits2(unsigned char *in, unsigned int *offset, unsigned int count) +{ //only reads up to 9 bits, because offset 7 with 10 bits needs to read more than two bytes + unsigned char r = ASTC_readbits(in, *offset, count); + *offset += count; + return r; +} +static void ASTC_Decode(unsigned char *in, unsigned char *out, int count, unsigned int offset, int bits, int extra, unsigned char *dequant) +{ + unsigned char block[5]; + int j; + + //unfortunately these trits depend upon the values of the later bits in each block. + //if only it were a nice simple modulo... + if (extra==1) + { + //read it 5 samples at a time + while(count > 0) + { + unsigned int t, c; + + block[0] = ASTC_readbits2(in, &offset, bits); + t = ASTC_readbits2(in, &offset, 2); + if (count > 1) + { + block[1] = ASTC_readbits2(in, &offset, bits); + t |= ASTC_readbits2(in, &offset, 2)<<2; + } + if (count > 2) + { + block[2] = ASTC_readbits2(in, &offset, bits); + t |= ASTC_readbits2(in, &offset, 1)<<4; + } + if (count > 3) + { + block[3] = ASTC_readbits2(in, &offset, bits); + t |= ASTC_readbits2(in, &offset, 2)<<5; + } + if (count > 4) + { + block[4] = ASTC_readbits2(in, &offset, bits); + t |= ASTC_readbits2(in, &offset, 1)<<7; + } + + //okay, we read the block, now figure out the trits and pack them into the high part of the result + if ((t&0x1c) == 0x1c) + { + c = ((t>>3)&0x1c) | (t&3); + block[4] |= 2<>7)<>7)<>5)&3)<>4)&1)<>2)&2) | ((c>>2)&~(c>>3)&1))<>4)&1)<>2)&3)<>1)))< 0) + { + unsigned int t, c; + + block[0] = ASTC_readbits2(in, &offset, bits); + t = ASTC_readbits2(in, &offset, 3); + if (count > 1) + { + block[1] = ASTC_readbits2(in, &offset, bits); + t |= ASTC_readbits2(in, &offset, 2)<<3; + } + if (count > 2) + { + block[2] = ASTC_readbits2(in, &offset, bits); + t |= ASTC_readbits2(in, &offset, 2)<<5; + } + + //okay, we read the block, now figure out the trits and pack them into the high part of the result + if ((t&6)==6 && !(t&0x60)) + { + block[2] |= (((t&1)<<2) | (((t>>4)&~t&1)<<1) | ((t>>3)&~t&1))<>3)&3)<<3; + c |= (~(t>>5)&3)<<1; + c |= t&1; + } + else + { + block[2] |= ((t>>5)&3)<>3)&3)<>3)&3)< 0) //pure bits, nice and simple + { + unsigned char val = ASTC_readbits2(in, &offset, bits); + + *out++ = dequant[val]; + } +} + +//endpoints have a logical value between 0 and 255. +//bit replication is used to fill in missing precision +static unsigned char dequant_ep_1b[1<<1] = {0,255}; +static unsigned char dequant_ep_2b[1<<2] = {0x00,0x55,0xaa,0xff}; +static unsigned char dequant_ep_3b[1<<3] = {0x00,0x24,0x49,0x6d,0x92,0xb6,0xdb,0xff}; +static unsigned char dequant_ep_4b[1<<4] = { + 0x00,0x11,0x22,0x33,0x44,0x55,0x66,0x77,0x88,0x99,0xaa,0xbb,0xcc,0xdd,0xee,0xff}; +static unsigned char dequant_ep_5b[1<<5] = { + 0x00,0x08,0x10,0x18,0x21,0x29,0x31,0x39,0x42,0x4a,0x52,0x5a,0x63,0x6b,0x73,0x7b, + 0x84,0x8c,0x94,0x9c,0xa5,0xad,0xb5,0xbd,0xc6,0xce,0xd6,0xde,0xe7,0xef,0xf7,0xff}; +static unsigned char dequant_ep_6b[1<<6] = { + 0x00,0x04,0x08,0x0c,0x10,0x14,0x18,0x1c,0x20,0x24,0x28,0x2c,0x30,0x34,0x38,0x3c, + 0x41,0x45,0x49,0x4d,0x51,0x55,0x59,0x5d,0x61,0x65,0x69,0x6d,0x71,0x75,0x79,0x7d, + 0x82,0x86,0x8a,0x8e,0x92,0x96,0x9a,0x9e,0xa2,0xa6,0xaa,0xae,0xb2,0xb6,0xba,0xbe, + 0xc3,0xc7,0xcb,0xcf,0xd3,0xd7,0xdb,0xdf,0xe3,0xe7,0xeb,0xef,0xf3,0xf7,0xfb,0xff}; +static unsigned char dequant_ep_7b[1<<7] = { + 0x00,0x02,0x04,0x06,0x08,0x0a,0x0c,0x0e,0x10,0x12,0x14,0x16,0x18,0x1a,0x1c,0x1e, + 0x20,0x22,0x24,0x26,0x28,0x2a,0x2c,0x2e,0x30,0x32,0x34,0x36,0x38,0x3a,0x3c,0x3e, + 0x40,0x42,0x44,0x46,0x48,0x4a,0x4c,0x4e,0x50,0x52,0x54,0x56,0x58,0x5a,0x5c,0x5e, + 0x60,0x62,0x64,0x66,0x68,0x6a,0x6c,0x6e,0x70,0x72,0x74,0x76,0x78,0x7a,0x7c,0x7e, + 0x81,0x83,0x85,0x87,0x89,0x8b,0x8d,0x8f,0x91,0x93,0x95,0x97,0x99,0x9b,0x9d,0x9f, + 0xa1,0xa3,0xa5,0xa7,0xa9,0xab,0xad,0xaf,0xb1,0xb3,0xb5,0xb7,0xb9,0xbb,0xbd,0xbf, + 0xc1,0xc3,0xc5,0xc7,0xc9,0xcb,0xcd,0xcf,0xd1,0xd3,0xd5,0xd7,0xd9,0xdb,0xdd,0xdf, + 0xe1,0xe3,0xe5,0xe7,0xe9,0xeb,0xed,0xef,0xf1,0xf3,0xf5,0xf7,0xf9,0xfb,0xfd,0xff}; +static unsigned char dequant_ep_8b[1<<8] = { + 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f, + 0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1a,0x1b,0x1c,0x1d,0x1e,0x1f, + 0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2a,0x2b,0x2c,0x2d,0x2e,0x2f, + 0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39,0x3a,0x3b,0x3c,0x3d,0x3e,0x3f, + 0x40,0x41,0x42,0x43,0x44,0x45,0x46,0x47,0x48,0x49,0x4a,0x4b,0x4c,0x4d,0x4e,0x4f, + 0x50,0x51,0x52,0x53,0x54,0x55,0x56,0x57,0x58,0x59,0x5a,0x5b,0x5c,0x5d,0x5e,0x5f, + 0x60,0x61,0x62,0x63,0x64,0x65,0x66,0x67,0x68,0x69,0x6a,0x6b,0x6c,0x6d,0x6e,0x6f, + 0x70,0x71,0x72,0x73,0x74,0x75,0x76,0x77,0x78,0x79,0x7a,0x7b,0x7c,0x7d,0x7e,0x7f, + 0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8a,0x8b,0x8c,0x8d,0x8e,0x8f, + 0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9a,0x9b,0x9c,0x9d,0x9e,0x9f, + 0xa0,0xa1,0xa2,0xa3,0xa4,0xa5,0xa6,0xa7,0xa8,0xa9,0xaa,0xab,0xac,0xad,0xae,0xaf, + 0xb0,0xb1,0xb2,0xb3,0xb4,0xb5,0xb6,0xb7,0xb8,0xb9,0xba,0xbb,0xbc,0xbd,0xbe,0xbf, + 0xc0,0xc1,0xc2,0xc3,0xc4,0xc5,0xc6,0xc7,0xc8,0xc9,0xca,0xcb,0xcc,0xcd,0xce,0xcf, + 0xd0,0xd1,0xd2,0xd3,0xd4,0xd5,0xd6,0xd7,0xd8,0xd9,0xda,0xdb,0xdc,0xdd,0xde,0xdf, + 0xe0,0xe1,0xe2,0xe3,0xe4,0xe5,0xe6,0xe7,0xe8,0xe9,0xea,0xeb,0xec,0xed,0xee,0xef, + 0xf0,0xf1,0xf2,0xf3,0xf4,0xf5,0xf6,0xf7,0xf8,0xf9,0xfa,0xfb,0xfc,0xfd,0xfe,0xff}; +static unsigned char dequant_ep_0t[3] = {0,128,255}; +static unsigned char dequant_ep_1t[6] = {0x00,0xff,0x33,0xcc,0x66,0x99}; +static unsigned char dequant_ep_2t[12] = {0x00,0xff,0x45,0xba,0x17,0xe8,0x5c,0xa3,0x2e,0xd1,0x74,0x8b}; +static unsigned char dequant_ep_3t[24] = {0x00,0xff,0x21,0xde,0x42,0xbd,0x63,0x9c,0x0b,0xf4,0x2c,0xd3,0x4d,0xb2,0x6e,0x91,0x16,0xe9,0x37,0xc8,0x58,0xa7,0x79,0x86}; +static unsigned char dequant_ep_4t[48] = {0x00,0xff,0x10,0xef,0x20,0xdf,0x30,0xcf,0x41,0xbe,0x51,0xae,0x61,0x9e,0x71,0x8e,0x05,0xfa,0x15,0xea,0x26,0xd9,0x36,0xc9,0x46,0xb9,0x56,0xa9,0x67,0x98,0x77,0x88,0x0b,0xf4,0x1b,0xe4,0x2b,0xd4,0x3b,0xc4,0x4c,0xb3,0x5c,0xa3,0x6c,0x93,0x7c,0x83}; +static unsigned char dequant_ep_5t[96] = {0x00,0xff,0x08,0xf7,0x10,0xef,0x18,0xe7,0x20,0xdf,0x28,0xd7,0x30,0xcf,0x38,0xc7,0x40,0xbf,0x48,0xb7,0x50,0xaf,0x58,0xa7,0x60,0x9f,0x68,0x97,0x70,0x8f,0x78,0x87,0x02,0xfd,0x0a,0xf5,0x12,0xed,0x1a,0xe5,0x23,0xdc,0x2b,0xd4,0x33,0xcc,0x3b,0xc4,0x43,0xbc,0x4b,0xb4,0x53,0xac,0x5b,0xa4,0x63,0x9c,0x6b,0x94,0x73,0x8c,0x7b,0x84,0x05,0xfa,0x0d,0xf2,0x15,0xea,0x1d,0xe2,0x25,0xda,0x2d,0xd2,0x35,0xca,0x3d,0xc2,0x46,0xb9,0x4e,0xb1,0x56,0xa9,0x5e,0xa1,0x66,0x99,0x6e,0x91,0x76,0x89,0x7e,0x81}; +static unsigned char dequant_ep_6t[192]= {0x00,0xff,0x04,0xfb,0x08,0xf7,0x0c,0xf3,0x10,0xef,0x14,0xeb,0x18,0xe7,0x1c,0xe3,0x20,0xdf,0x24,0xdb,0x28,0xd7,0x2c,0xd3,0x30,0xcf,0x34,0xcb,0x38,0xc7,0x3c,0xc3,0x40,0xbf,0x44,0xbb,0x48,0xb7,0x4c,0xb3,0x50,0xaf,0x54,0xab,0x58,0xa7,0x5c,0xa3,0x60,0x9f,0x64,0x9b,0x68,0x97,0x6c,0x93,0x70,0x8f,0x74,0x8b,0x78,0x87,0x7c,0x83,0x01,0xfe,0x05,0xfa,0x09,0xf6,0x0d,0xf2,0x11,0xee,0x15,0xea,0x19,0xe6,0x1d,0xe2,0x21,0xde,0x25,0xda,0x29,0xd6,0x2d,0xd2,0x31,0xce,0x35,0xca,0x39,0xc6,0x3d,0xc2,0x41,0xbe,0x45,0xba,0x49,0xb6,0x4d,0xb2,0x51,0xae,0x55,0xaa,0x59,0xa6,0x5d,0xa2,0x61,0x9e,0x65,0x9a,0x69,0x96,0x6d,0x92,0x71,0x8e,0x75,0x8a,0x79,0x86,0x7d,0x82,0x02,0xfd,0x06,0xf9,0x0a,0xf5,0x0e,0xf1,0x12,0xed,0x16,0xe9,0x1a,0xe5,0x1e,0xe1,0x22,0xdd,0x26,0xd9,0x2a,0xd5,0x2e,0xd1,0x32,0xcd,0x36,0xc9,0x3a,0xc5,0x3e,0xc1,0x42,0xbd,0x46,0xb9,0x4a,0xb5,0x4e,0xb1,0x52,0xad,0x56,0xa9,0x5a,0xa5,0x5e,0xa1,0x62,0x9d,0x66,0x99,0x6a,0x95,0x6e,0x91,0x72,0x8d,0x76,0x89,0x7a,0x85,0x7e,0x81}; +static unsigned char dequant_ep_0q[5] = {0,64,128,192,255}; +static unsigned char dequant_ep_1q[10] = {0x00,0xff,0x1c,0xe3,0x38,0xc7,0x54,0xab,0x71,0x8e}; +static unsigned char dequant_ep_2q[20] = {0x00,0xff,0x43,0xbc,0x0d,0xf2,0x50,0xaf,0x1b,0xe4,0x5e,0xa1,0x28,0xd7,0x6b,0x94,0x36,0xc9,0x79,0x86}; +static unsigned char dequant_ep_3q[40] = {0x00,0xff,0x20,0xdf,0x41,0xbe,0x61,0x9e,0x06,0xf9,0x27,0xd8,0x47,0xb8,0x68,0x97,0x0d,0xf2,0x2d,0xd2,0x4e,0xb1,0x6e,0x91,0x13,0xec,0x34,0xcb,0x54,0xab,0x75,0x8a,0x1a,0xe5,0x3a,0xc5,0x5b,0xa4,0x7b,0x84}; +static unsigned char dequant_ep_4q[80] = {0x00,0xff,0x10,0xef,0x20,0xdf,0x30,0xcf,0x40,0xbf,0x50,0xaf,0x60,0x9f,0x70,0x8f,0x03,0xfc,0x13,0xec,0x23,0xdc,0x33,0xcc,0x43,0xbc,0x53,0xac,0x64,0x9b,0x74,0x8b,0x06,0xf9,0x16,0xe9,0x26,0xd9,0x36,0xc9,0x47,0xb8,0x57,0xa8,0x67,0x98,0x77,0x88,0x09,0xf6,0x19,0xe6,0x2a,0xd5,0x3a,0xc5,0x4a,0xb5,0x5a,0xa5,0x6a,0x95,0x7a,0x85,0x0d,0xf2,0x1d,0xe2,0x2d,0xd2,0x3d,0xc2,0x4d,0xb2,0x5d,0xa2,0x6d,0x92,0x7d,0x82}; +static unsigned char dequant_ep_5q[160]= {0x00,0xff,0x08,0xf7,0x10,0xef,0x18,0xe7,0x20,0xdf,0x28,0xd7,0x30,0xcf,0x38,0xc7,0x40,0xbf,0x48,0xb7,0x50,0xaf,0x58,0xa7,0x60,0x9f,0x68,0x97,0x70,0x8f,0x78,0x87,0x01,0xfe,0x09,0xf6,0x11,0xee,0x19,0xe6,0x21,0xde,0x29,0xd6,0x31,0xce,0x39,0xc6,0x41,0xbe,0x49,0xb6,0x51,0xae,0x59,0xa6,0x61,0x9e,0x69,0x96,0x71,0x8e,0x79,0x86,0x03,0xfc,0x0b,0xf4,0x13,0xec,0x1b,0xe4,0x23,0xdc,0x2b,0xd4,0x33,0xcc,0x3b,0xc4,0x43,0xbc,0x4b,0xb4,0x53,0xac,0x5b,0xa4,0x63,0x9c,0x6b,0x94,0x73,0x8c,0x7b,0x84,0x04,0xfb,0x0c,0xf3,0x14,0xeb,0x1c,0xe3,0x24,0xdb,0x2c,0xd3,0x34,0xcb,0x3c,0xc3,0x44,0xbb,0x4c,0xb3,0x54,0xab,0x5c,0xa3,0x64,0x9b,0x6c,0x93,0x74,0x8b,0x7c,0x83,0x06,0xf9,0x0e,0xf1,0x16,0xe9,0x1e,0xe1,0x26,0xd9,0x2e,0xd1,0x36,0xc9,0x3e,0xc1,0x46,0xb9,0x4e,0xb1,0x56,0xa9,0x5e,0xa1,0x66,0x99,0x6e,0x91,0x76,0x89,0x7e,0x81}; +static const struct +{ + unsigned char extra, bits, *dequant; +} astc_epvmode[] = +{ + {0,1, dequant_ep_1b}, //2 + {1,0, dequant_ep_0t}, //3 + {0,2, dequant_ep_2b}, //4 + {2,0, dequant_ep_0q}, //5 + {1,1, dequant_ep_1t}, //6 + {0,3, dequant_ep_3b}, //8 + {2,1, dequant_ep_1q}, //10 + {1,2, dequant_ep_2t}, //12 + {0,4, dequant_ep_4b}, //16 + {2,2, dequant_ep_2q}, //20 + {1,3, dequant_ep_3t}, //24 + {0,5, dequant_ep_5b}, //32 + {2,3, dequant_ep_3q}, //40 + {1,4, dequant_ep_4t}, //48 + {0,6, dequant_ep_6b}, //64 + {2,4, dequant_ep_4q}, //80 + {1,5, dequant_ep_5t}, //96 + {0,7, dequant_ep_7b}, //128 + {2,5, dequant_ep_5q}, //160 + {1,6, dequant_ep_6t}, //192 + {0,8, dequant_ep_8b}, //256 + //other modes don't make any sense +}; +/*static void ASTC_CalcDequant(void) +{ + int i; + + int extra = 0; + int bits = 1; + int isweight = 1; + int targbits = isweight?6:8; + int v; + + static qboolean nospam; + if (nospam) + return; + nospam = true; + + //binary: + if (!extra) + { + for (bits = 1; bits <= (isweight?5:8); bits++) + { + Con_Printf("table: %s_%ib", isweight?"weight":"ep", bits); + for (i = 0; i < (1<>bits; + v|=v>>bits; + v|=v>>bits; + v|=v>>bits; + v|=v>>bits; + v|=v>>bits; + v|=v>>bits; + v|=v>>bits; + + if (isweight && v > 32) + v++; //0-64 instead of 0-63 + + Con_Printf("0x%02x,", v); + } + Con_Printf("\n"); + } + } + else if (extra == 1) + { + int A,B,C,D; + + for (bits = 1; bits <= (isweight?3:6); bits++) + { + Con_Printf("table: %s_%it:\n", isweight?"weight":"ep", bits); + for (i = 0; i < ((2<>bits; + break; + case 2: + A = (i&1)*(isweight?0x7f:0x1ff); + B = ((i>>1)&1) * (isweight?0b1000101:0b100010110); + C = isweight?25:93; + D = i>>bits; + break; + case 3: + A = (i&1)*(isweight?0x7f:0x1ff); + B = ((i>>1)&1) * (isweight?0b0100001:0b010000101); //b + B|= ((i>>2)&1) * (isweight?0b1000010:0b100001010); //c + C = isweight?11:44; + D = i>>bits; + break; + case 4: + A = (i&1)*0x1ff; + B = ((i>>1)&1) * 0b001000001; //b + B|= ((i>>2)&1) * 0b010000010; //c + B|= ((i>>3)&1) * 0b100000100; //d + C = 22; + D = i>>bits; + break; + case 5: + A = (i&1)*0x1ff; + B = ((i>>1)&1) * 0b000100000; //b + B|= ((i>>2)&1) * 0b001000000; //c + B|= ((i>>3)&1) * 0b010000001; //d + B|= ((i>>4)&1) * 0b100000010; //e + C = 11; + D = i>>bits; + break; + case 6: + A = (i&1)*0x1ff; + B = ((i>>1)&1) * 0b000010000; //b + B|= ((i>>2)&1) * 0b000100000; //c + B|= ((i>>3)&1) * 0b001000000; //d + B|= ((i>>4)&1) * 0b010000000; //e + B|= ((i>>5)&1) * 0b100000001; //f + C = 5; + D = i>>bits; + break; + } + v = D * C + B; + v = v ^ A; + v = (A & (isweight?0x20:0x80)) | (v >> 2); + + if (isweight && v > 32) + v++; //0-64 instead of 0-63 + + Con_Printf("0x%02x,", v); + } + Con_Printf("\n"); + } + } + else if (extra == 2) + { + int A,B,C,D; + + for (bits = 1; bits <= (isweight?2:5); bits++) + { + Con_Printf("table: %s_%iq:\n", isweight?"weight":"ep", bits); + for (i = 0; i < ((4<>bits; + break; + case 2: + A = (i&1)*(isweight?0x7f:0x1ff); + B = ((i>>1)&1) * (isweight?0b1000010:0b100001100); + C = isweight?13:54; + D = i>>bits; + break; + case 3: + A = (i&1)*0x1ff; + B = ((i>>1)&1) * 0b010000010; //b + B|= ((i>>2)&1) * 0b100000101; //c + C = 26; + D = i>>bits; + break; + case 4: + A = (i&1)*0x1ff; + B = ((i>>1)&1) * 0b001000000; //b + B|= ((i>>2)&1) * 0b010000001; //c + B|= ((i>>3)&1) * 0b100000010; //d + C = 13; + D = i>>bits; + break; + case 5: + A = (i&1)*0x1ff; + B = ((i>>1)&1) * 0b000100000; //b + B|= ((i>>2)&1) * 0b001000000; //c + B|= ((i>>3)&1) * 0b010000000; //d + B|= ((i>>4)&1) * 0b100000001; //e + C = 6; + D = i>>bits; + break; + } + v = D * C + B; + v = v ^ A; + v = (A & (isweight?0x20:0x80)) | (v >> 2); + + if (isweight && v > 32) + v++; //0-64 instead of 0-63 + + Con_Printf("0x%02x,", v); + } + Con_Printf("\n"); + } + } +}*/ + +static void ASTC_blue_contract(int *out, int r, int g, int b, int a) +{ + out[0] = (r+b) >> 1; + out[1] = (g+b) >> 1; + out[2] = b; + out[3] = a; +} +static int ASTC_bit_transfer_signed(int a, unsigned char *b) //returns new value for a. +{ + *b >>= 1; + *b |= a & 0x80; + a >>= 1; + a &= 0x3F; + if((a&0x20)!=0) + a=a-0x40; + return a; +} +static void ASTC_clamp_unorm8(int *c) +{ + c[0] = bound(0, c[0], 255); + c[1] = bound(0, c[1], 255); + c[2] = bound(0, c[2], 255); + c[3] = bound(0, c[3], 255); +} + +#ifdef ASTC_WITH_HDR +static void ASTC_HDR_Mode_2(struct astc_part *p, unsigned char *v) +{ + int y0,y1; + if(v[1] >= v[0]) + { + y0 = (v[0] << 4); + y1 = (v[1] << 4); + } + else + { + y0 = (v[1] << 4) + 8; + y1 = (v[0] << 4) - 8; + } + Vector4Set(p->ep[0], y0, y0, y0, 0x780); + Vector4Set(p->ep[1], y1, y1, y1, 0x780); + p->hdr = 0xf; +} +static void ASTC_HDR_Mode_3(struct astc_part *p, unsigned char *v) +{ + int y0, y1, d; + if((v[0]&0x80) != 0) + { + y0 = ((v[1] & 0xE0) << 4) | ((v[0] & 0x7F) << 2); + d = (v[1] & 0x1F) << 2; + } + else + { + y0 = ((v[1] & 0xF0) << 4) | ((v[0] & 0x7F) << 1); + d = (v[1] & 0x0F) << 1; + } + + y1 = y0 + d; + if(y1 > 0xFFF) + y1 = 0xFFF; + + Vector4Set(p->ep[0], y0, y0, y0, 0x780); + Vector4Set(p->ep[1], y1, y1, y1, 0x780); + p->hdr = 0xf; +} +static void ASTC_HDR_Mode_7(struct astc_part *p, unsigned char *v) +{ + int modeval = ((v[0]&0xC0)>>6) | ((v[1]&0x80)>>5) | ((v[2]&0x80)>>4); + int majcomp; + int mode; + static const int shamts[6] = { 1,1,2,3,4,5 }; + int shamt,t; + + int red, green, blue, scale; + int x0,x1,x2,x3,x4,x5,x6,ohm; + + if( (modeval & 0xC ) != 0xC ) + { + majcomp = modeval >> 2; + mode = modeval & 3; + } + else if( modeval != 0xF ) + { + majcomp = modeval & 3; + mode = 4; + } + else + { + majcomp = 0; mode = 5; + } + + red = v[0] & 0x3f; + green = v[1] & 0x1f; + blue = v[2] & 0x1f; + scale = v[3] & 0x1f; + + x0 = (v[1] >> 6) & 1; x1 = (v[1] >> 5) & 1; + x2 = (v[2] >> 6) & 1; x3 = (v[2] >> 5) & 1; + x4 = (v[3] >> 7) & 1; x5 = (v[3] >> 6) & 1; + x6 = (v[3] >> 5) & 1; + + ohm = 1 << mode; + if( ohm & 0x30 ) green |= x0 << 6; + if( ohm & 0x3A ) green |= x1 << 5; + if( ohm & 0x30 ) blue |= x2 << 6; + if( ohm & 0x3A ) blue |= x3 << 5; + if( ohm & 0x3D ) scale |= x6 << 5; + if( ohm & 0x2D ) scale |= x5 << 6; + if( ohm & 0x04 ) scale |= x4 << 7; + if( ohm & 0x3B ) red |= x4 << 6; + if( ohm & 0x04 ) red |= x3 << 6; + if( ohm & 0x10 ) red |= x5 << 7; + if( ohm & 0x0F ) red |= x2 << 7; + if( ohm & 0x05 ) red |= x1 << 8; + if( ohm & 0x0A ) red |= x0 << 8; + if( ohm & 0x05 ) red |= x0 << 9; + if( ohm & 0x02 ) red |= x6 << 9; + if( ohm & 0x01 ) red |= x3 << 10; + if( ohm & 0x02 ) red |= x5 << 10; + + shamt = shamts[mode]; + red <<= shamt; green <<= shamt; blue <<= shamt; scale <<= shamt; + + if( mode != 5 ) { green = red - green; blue = red - blue; } + + if( majcomp == 1 ) + { + t = red; + red = green; + green = t; + } + if( majcomp == 2 ) + { + t = red; + red = blue; + blue = t; + } + + p->ep[1][0] = bound( 0, red, 0xFFF ); + p->ep[1][1] = bound( 0, green, 0xFFF ); + p->ep[1][2] = bound( 0, blue, 0xFFF ); + + p->ep[0][0] = bound( 0, red - scale, 0xFFF ); + p->ep[0][1] = bound( 0, green - scale, 0xFFF ); + p->ep[0][2] = bound( 0, blue - scale, 0xFFF ); + + p->ep[1][3] = p->ep[0][3] = 0x780; + + p->hdr = 0xf; +} +static void ASTC_HDR_Mode_11(struct astc_part *p, unsigned char *v) +{ + static const int dbitstab[8] = {7,6,7,6,5,6,5,6}; + int shamt; + int majcomp = ((v[4] & 0x80) >> 7) | ((v[5] & 0x80) >> 6); + int mode,va,vb0,vb1,vc,vd0,vd1; + int x0,x1,x2,x3,x4,x5,ohm; + + if( majcomp == 3 ) + { + Vector4Set(p->ep[0], v[0] << 4, v[2] << 4, (v[4] & 0x7f) << 5, 0x780); + Vector4Set(p->ep[1], v[1] << 4, v[3] << 4, (v[5] & 0x7f) << 5, 0x780); + p->hdr = 0xf; + return; + } + + mode = ((v[1]&0x80)>>7) | ((v[2]&0x80)>>6) | ((v[3]&0x80)>>5); + va = v[0] | ((v[1] & 0x40) << 2); + vb0 = v[2] & 0x3f; + vb1 = v[3] & 0x3f; + vc = v[1] & 0x3f; + vd0 = v[4] & 0x7f; + vd1 = v[5] & 0x7f; + + if (vd0 & (1<<(dbitstab[mode]-1))) + vd0 |= -1 & ~((1u<> 6) & 1; + x1 = (v[3] >> 6) & 1; + x2 = (v[4] >> 6) & 1; + x3 = (v[5] >> 6) & 1; + x4 = (v[4] >> 5) & 1; + x5 = (v[5] >> 5) & 1; + + ohm = 1 << mode; + if( ohm & 0xA4 ) va |= x0 << 9; + if( ohm & 0x08 ) va |= x2 << 9; + if( ohm & 0x50 ) va |= x4 << 9; + if( ohm & 0x50 ) va |= x5 << 10; + if( ohm & 0xA0 ) va |= x1 << 10; + if( ohm & 0xC0 ) va |= x2 << 11; + if( ohm & 0x04 ) vc |= x1 << 6; + if( ohm & 0xE8 ) vc |= x3 << 6; + if( ohm & 0x20 ) vc |= x2 << 7; + if( ohm & 0x5B ) vb0 |= x0 << 6; + if( ohm & 0x5B ) vb1 |= x1 << 6; + if( ohm & 0x12 ) vb0 |= x2 << 7; + if( ohm & 0x12 ) vb1 |= x3 << 7; + + // Now shift up so that major component is at top of 12-bit value + shamt = (mode >> 1) ^ 3; + va <<= shamt; vb0 <<= shamt; vb1 <<= shamt; + vc <<= shamt; vd0 <<= shamt; vd1 <<= shamt; + + p->ep[1][0] = bound( 0, va, 0xFFF ); + p->ep[1][1] = bound( 0, va - vb0, 0xFFF ); + p->ep[1][2] = bound( 0, va - vb1, 0xFFF ); + + p->ep[0][0] = bound( 0, va - vc, 0xFFF ); + p->ep[0][1] = bound( 0, va - vb0 - vc - vd0, 0xFFF ); + p->ep[0][2] = bound( 0, va - vb1 - vc - vd1, 0xFFF ); + + if( majcomp == 1 ) + { + p->ep[0][3] = p->ep[0][0]; + p->ep[0][0] = p->ep[0][1]; + p->ep[0][1] = p->ep[0][3]; + p->ep[1][3] = p->ep[1][0]; + p->ep[1][0] = p->ep[1][1]; + p->ep[1][1] = p->ep[1][3]; + } + else if( majcomp == 2 ) + { + p->ep[0][3] = p->ep[0][0]; + p->ep[0][0] = p->ep[0][2]; + p->ep[0][2] = p->ep[0][3]; + p->ep[1][3] = p->ep[1][0]; + p->ep[1][0] = p->ep[1][2]; + p->ep[1][2] = p->ep[1][3]; + } + + p->ep[0][3] = p->ep[1][3] = 0x780; + + p->hdr = 0xf; +} +static void ASTC_HDR_Mode_14(struct astc_part *p, unsigned char *v) +{ + ASTC_HDR_Mode_11(p, v); + + p->ep[0][3] = v[6]; + p->ep[1][3] = v[7]; + p->hdr &= 0x7; +} +static void ASTC_HDR_Mode_15(struct astc_part *p, unsigned char *v) +{ + int v6=v[6], v7=v[7]; + int mode; + ASTC_HDR_Mode_11(p,v); + + mode = ((v6 >> 7) & 1) | ((v7 >> 6) & 2); + v6 &= 0x7F; + v7 &= 0x7F; + + if(mode==3) + { + p->ep[0][3] = v6 << 5; + p->ep[1][3] = v7 << 5; + } + else + { + v6 |= (v7 << (mode+1)) & 0x780; + v7 &= (0x3F >> mode); + v7 ^= 0x20 >> mode; + v7 -= 0x20 >> mode; + v6 <<= (4-mode); + v7 <<= (4-mode); + + v7 += v6; + v7 = bound(0, v7, 0xFFF); + p->ep[0][3] = v6; + p->ep[1][3] = v7; + } +} +#endif + +static void ASTC_DecodeEndpoints(struct astc_block_info *b, unsigned char *v) +{ + int i, t0, t1, t3, t5, t7; + + for (i = 0; i < b->partitions; i++) + { +#ifdef ASTC_WITH_HDR + b->part[i].hdr = 0; +#endif + switch (b->part[i].mode & 15) + { +#ifdef ASTC_WITH_HDR + case 2: //HDR Luminance, large range + ASTC_HDR_Mode_2(&b->part[i], v); + break; + case 3: //HDR Luminance, small range + ASTC_HDR_Mode_3(&b->part[i], v); + break; + case 7: //HDR RGB, base+scale + ASTC_HDR_Mode_7(&b->part[i], v); + break; + case 11: //HDR RGB + ASTC_HDR_Mode_11(&b->part[i], v); + break; + case 14: //HDR RGB + LDR Alpha + ASTC_HDR_Mode_14(&b->part[i], v); + break; + case 15: //HDR RGB + HDR Alpha + ASTC_HDR_Mode_15(&b->part[i], v); + break; +#endif + default: //the error colour - for unsupported hdr endpoints. unreachable when hdr is enabled. just fill it with the error colour. + Vector4Set(b->part[i].ep[0], 0xff, 0, 0xff, 0xff); + Vector4Set(b->part[i].ep[1], 0xff, 0, 0xff, 0xff); + break; + + case 0: //LDR Luminance, direct + Vector4Set(b->part[i].ep[0], v[0], v[0], v[0], 0xff); + Vector4Set(b->part[i].ep[1], v[1], v[1], v[1], 0xff); + break; + case 1: //LDR Luminance, base+offset + t0 = (v[0]>>2)|(v[1]&0xc0); + t1 = t0+(v[1]&0x3f); + if (t1>0xff) + t1=0xff; + Vector4Set(b->part[i].ep[0], t0, t0, t0, 0xff); + Vector4Set(b->part[i].ep[1], t1, t1, t1, 0xff); + break; + case 4: //LDR Luminance+Alpha,direct + Vector4Set(b->part[i].ep[0], v[0], v[0], v[0], v[2]); + Vector4Set(b->part[i].ep[1], v[1], v[1], v[1], v[3]); + break; + case 5: //LDR Luminance+Alpha, base+offset + t1 = ASTC_bit_transfer_signed(v[1],&v[0]); + t3 = ASTC_bit_transfer_signed(v[3],&v[2]); + Vector4Set(b->part[i].ep[0],v[0],v[0],v[0],v[2]); + Vector4Set(b->part[i].ep[1],v[0]+t1,v[0]+t1,v[0]+t1,v[2]+t3); + ASTC_clamp_unorm8(b->part[i].ep[0]); + ASTC_clamp_unorm8(b->part[i].ep[1]); + break; + case 6: //LDR RGB, base+scale + Vector4Set(b->part[i].ep[0], ((int)v[0]*(int)v[3])>>8, ((int)v[1]*(int)v[3])>>8, ((int)v[2]*(int)v[3])>>8, 0xff); + Vector4Set(b->part[i].ep[1], v[0], v[1], v[2], 0xff); + break; + case 8: //LDR RGB, Direct + t0 = (int)v[0]+(int)v[2]+(int)v[4]; + t1 = (int)v[1]+(int)v[3]+(int)v[5]; + if (t1>=t0) + { + Vector4Set(b->part[i].ep[0], v[0],v[2],v[4],0xff); + Vector4Set(b->part[i].ep[1], v[1],v[3],v[5],0xff); + } + else + { + ASTC_blue_contract(b->part[i].ep[0], v[1],v[3],v[5], 0xff); + ASTC_blue_contract(b->part[i].ep[1], v[0],v[2],v[4], 0xff); + } + break; + case 9: //LDR RGB, base+offset + t1 = ASTC_bit_transfer_signed(v[1],&v[0]); + t3 = ASTC_bit_transfer_signed(v[3],&v[2]); + t5 = ASTC_bit_transfer_signed(v[5],&v[4]); + if(t1+t3+t5 >= 0) + { + Vector4Set(b->part[i].ep[0],v[0],v[2],v[4],0xff); + Vector4Set(b->part[i].ep[1],v[0]+t1,v[2]+t3,v[4]+t5,0xff); + } + else + { + ASTC_blue_contract(b->part[i].ep[0], v[0]+t1,v[2]+t3,v[4]+t5, 0xff); + ASTC_blue_contract(b->part[i].ep[1], v[0],v[2],v[4], 0xff); + } + ASTC_clamp_unorm8(b->part[i].ep[0]); + ASTC_clamp_unorm8(b->part[i].ep[1]); + break; + case 10: //LDR RGB, base+scale plus two A + Vector4Set(b->part[i].ep[0], ((int)v[0]*v[3])>>8, ((int)v[1]*v[3])>>8, ((int)v[2]*v[3])>>8, v[4]); + Vector4Set(b->part[i].ep[1], v[0], v[1], v[2], v[5]); + break; + case 12: //LDR RGBA, direct + if (v[1]+(int)v[3]+v[5]>=v[0]+(int)v[2]+v[4]) + { + Vector4Set(b->part[i].ep[0], v[0],v[2],v[4],v[6]); + Vector4Set(b->part[i].ep[1], v[1],v[3],v[5],v[7]); + } + else + { + ASTC_blue_contract(b->part[i].ep[0], v[1],v[3],v[5],v[7]); + ASTC_blue_contract(b->part[i].ep[1], v[0],v[2],v[4],v[6]); + } + break; + case 13: //LDR RGBA, base+offset + t1 = ASTC_bit_transfer_signed(v[1],&v[0]); + t3 = ASTC_bit_transfer_signed(v[3],&v[2]); + t5 = ASTC_bit_transfer_signed(v[5],&v[4]); + t7 = ASTC_bit_transfer_signed(v[7],&v[6]); + if(t1+t3+t5>=0) + { + Vector4Set(b->part[i].ep[0], v[0],v[2],v[4],v[6]); + Vector4Set(b->part[i].ep[1], v[0]+t1,v[2]+t3,v[4]+t5,v[6]+t7); + } + else + { + ASTC_blue_contract(b->part[i].ep[0], v[0]+t1,v[2]+t3,v[4]+t5,v[6]+t7); + ASTC_blue_contract(b->part[i].ep[1], v[0],v[2],v[4],v[6]); + } + ASTC_clamp_unorm8(b->part[i].ep[0]); + ASTC_clamp_unorm8(b->part[i].ep[1]); + break; + } + v += ((b->part[i].mode>>2)+1)<<1; + } +} +static void ASTC_ReadEndpoints(struct astc_block_info *b) +{ + int i; + int cembits; + + unsigned char epv[18]; //maximum raw endpoint values, + char epvalues; + unsigned char gahffs[16], t; + + //figure out how many raw values we need + epvalues = 0; + for (i = 0; i < b->partitions; i++) + epvalues += ((b->part[i].mode>>2)+1)<<1; + if (epvalues > countof(epv)) + { + b->status = ASTC_ERROR; + return; + } + + //the endpoint bits are encoded using the largest size available that'll still fit, yielding raw values between 0-255. + for(i = countof(astc_epvmode)-1; i >= 0; i--) + { + cembits = ASTC_DecodeSize(epvalues, astc_epvmode[i].bits, astc_epvmode[i].extra); + if(cembits <= b->ep_bits) + { + //read the values. + ASTC_Decode(b->in, epv, epvalues, b->config_bits, astc_epvmode[i].bits, astc_epvmode[i].extra, astc_epvmode[i].dequant); + //and decode them. + ASTC_DecodeEndpoints(b, epv); + + //weight bits are backwards (gah! ffs!) + //so swap them around so our decode function doesn't need to care + for (i = 0; i < countof(gahffs); i++) + { + t = b->in[i]; + t = (t>>4)|(t<<4); + t = ((t&0xcc)>>2)|((t&0x33)<<2); + t = ((t&0xaa)>>1)|((t&0x55)<<1); + gahffs[15-i] = t; + } + //weights are aligned at the end... now the start. gah! ffs! + ASTC_Decode(gahffs, b->weights, b->wcount[3], 0, astc_weightmode[b->precision].bits, astc_weightmode[b->precision].extra, astc_weightmode[b->precision].dequant); + return; + } + } + b->status = ASTC_ERROR; +} + +static unsigned int hash52(unsigned int p) +{ + p ^= p >> 15; p -= p << 17; p += p << 7; p += p << 4; + p ^= p >> 5; p += p << 16; p ^= p >> 7; p ^= p >> 3; + p ^= p << 6; p ^= p >> 17; + return p; +} +static int ASTC_ChoosePartition(int seed, int x, int y, int z, int partitions, int smallblock) +{ + int sh1, sh2, sh3, a,b,c,d; + unsigned int rnum; + unsigned char seed1,seed2,seed3,seed4,seed5,seed6,seed7,seed8,seed9,seed10,seed11,seed12; + if (partitions==1) + return 0; + if (smallblock) + { + x <<= 1; + y <<= 1; + z <<= 1; + } + seed += (partitions-1) * 1024; + rnum = hash52(seed); + seed1 = rnum & 0xF; + seed2 = (rnum >> 4) & 0xF; + seed3 = (rnum >> 8) & 0xF; + seed4 = (rnum >> 12) & 0xF; + seed5 = (rnum >> 16) & 0xF; + seed6 = (rnum >> 20) & 0xF; + seed7 = (rnum >> 24) & 0xF; + seed8 = (rnum >> 28) & 0xF; + seed9 = (rnum >> 18) & 0xF; + seed10 = (rnum >> 22) & 0xF; + seed11 = (rnum >> 26) & 0xF; + seed12 = ((rnum >> 30) | (rnum << 2)) & 0xF; + + seed1 *= seed1; seed2 *= seed2; + seed3 *= seed3; seed4 *= seed4; + seed5 *= seed5; seed6 *= seed6; + seed7 *= seed7; seed8 *= seed8; + seed9 *= seed9; seed10 *= seed10; + seed11 *= seed11; seed12 *= seed12; + + + if (seed & 1) + { + sh1 = ((seed&2) ? 4:5); + sh2 = ((partitions==3) ? 6:5); + } + else + { + sh1 = ((partitions==3) ? 6:5); + sh2 = ((seed&2) ? 4:5); + } + sh3 = (seed & 0x10) ? sh1 : sh2; + + seed1 >>= sh1; seed2 >>= sh2; seed3 >>= sh1; seed4 >>= sh2; + seed5 >>= sh1; seed6 >>= sh2; seed7 >>= sh1; seed8 >>= sh2; + seed9 >>= sh3; seed10 >>= sh3; seed11 >>= sh3; seed12 >>= sh3; + + a = seed1*x + seed2*y + seed11*z + (rnum >> 14); + b = seed3*x + seed4*y + seed12*z + (rnum >> 10); + c = seed5*x + seed6*y + seed9 *z + (rnum >> 6); + d = seed7*x + seed8*y + seed10*z + (rnum >> 2); + + a &= 0x3F; b &= 0x3F; c &= 0x3F; d &= 0x3F; + + if (partitions < 4) + d = 0; + if (partitions < 3) + c = 0; + + if (a >= b && a >= c && a >= d) + return 0; + else if (b >= c && b >= d) + return 1; + else if (c >= d) + return 2; + else + return 3; +} +#endif + +#ifdef ASTC_WITH_LDR +//Spits out 8-bit RGBA data for a single block. Any HDR blocks will result in the error colour. +//sRGB can be applied by the caller, if needed. +ASTC_PUBLIC void ASTC_Decode_LDR8(unsigned char *in, unsigned char *out, int pixstride, int bw, int bh) +{ + struct astc_block_info b; + int x, y; + int stride = pixstride*4; + b.in = in; + b.blocksize[0] = bw; + b.blocksize[1] = bh; + b.blocksize[2] = 1; + + ASTC_ReadBlockMode(&b); + + if (b.status == ASTC_VOID_LDR) + { //void extent + //Note: we don't validate the extents. + for (y = 0; y < bh; y++, out += stride) + for (x = 0; x < bw; x++) + { + out[(x<<2)+0] = in[9]; + out[(x<<2)+1] = in[11]; + out[(x<<2)+2] = in[13]; + out[(x<<2)+3] = in[15]; + } + return; + } + + if (b.status == ASTC_OKAY) + ASTC_ReadPartitions(&b); + if (b.status == ASTC_OKAY) + ASTC_ReadEndpoints(&b); + + if (b.status == ASTC_OKAY) + { + int smallblock = (b.blocksize[0]*b.blocksize[1]*b.blocksize[2])<31; + int ds = (1024+b.blocksize[0]/2)/(b.blocksize[0]-1); + int dt = (1024+b.blocksize[1]/2)/(b.blocksize[1]-1); + int planes = 1<>6; + for (y = 0; y < bh; y++, out += stride) + { + t = ((dt*y)*(b.wcount[1]-1)+32)>>6; + for (x = 0; x < bw; x++) + { + p = &b.part[ASTC_ChoosePartition(b.partindex, x,y,0, b.partitions, smallblock)]; + s = ((ds*x)*(b.wcount[0]-1)+32)>>6; + w11 = ((s&0xf)*(t&0xf)+8) >> 4; + w10 = (t&0xf) - w11; + w01 = (s&0xf) - w11; + w00 = 16 - (s&0xf) - (t&0xf) + w11; + + v0 = (((s>>4))<>4))*wstride); + w = ( w00*b.weights[v0] + + w01*b.weights[v0+planes] + + w10*b.weights[v0+wstride] + + w11*b.weights[v0+planes+wstride] + 8) >> 4; + out[(x<<2)+0] = ((64-w)*p->ep[0][0] + w*p->ep[1][0])>>6; + out[(x<<2)+1] = ((64-w)*p->ep[0][1] + w*p->ep[1][1])>>6; + out[(x<<2)+2] = ((64-w)*p->ep[0][2] + w*p->ep[1][2])>>6; + out[(x<<2)+3] = ((64-w)*p->ep[0][3] + w*p->ep[1][3])>>6; + + if (b.dualplane) + { //dual planes has a second set of weights that override a single channel + v0++; + w = ( w00*b.weights[v0] + + w01*b.weights[v0+planes] + + w10*b.weights[v0+wstride] + + w11*b.weights[v0+planes+wstride] + 8) >> 4; + out[(x<<2)+b.ccs] = ((64-w)*p->ep[0][b.ccs] + w*p->ep[1][b.ccs])>>6; + } + } + } + } + } + else + { + for (y = 0; y < bh; y++, out += stride) + for (x = 0; x < bw; x++) + { + out[(x<<2)+0] = 0xff; + out[(x<<2)+1] = 0; + out[(x<<2)+2] = 0xff; + out[(x<<2)+3] = 0xff; + } + } +} +#endif + +#ifdef ASTC_WITH_HDR +static unsigned short ASTC_GenHalffloat(int hdr, int rawval) +{ + if (hdr) + { + int fp16, m; + fp16 = (rawval&0xF800) >> 1; + m = rawval&0x7FF; + if (m < 512) + fp16 |= (3*m)>>3; + else if (m >= 1536) + fp16 |= (5*m - 2048)>>3; + else + fp16 |= (4*m - 512)>>3; + return fp16; + } + else + { + union + { + float f; + unsigned int u; + } u = {rawval/65535.0}; + int e = 0; + int m; + + e = ((u.u>>23)&0xff) - 127; + if (e < -15) + return 0; //too small exponent, treat it as a 0 denormal + if (e > 15) + m = 0; //infinity instead of a nan + else + m = (u.u&((1<<23)-1))>>13; + return ((e+15)<<10) | m; + } +} + +//Spits out half-float RGBA data for a single block. +ASTC_PUBLIC void ASTC_Decode_HDR(unsigned char *in, unsigned short *out, int pixstride, int bw, int bh) +{ + int x, y; + int stride = pixstride*4; + struct astc_block_info b; + b.in = in; + b.blocksize[0] = bw; + b.blocksize[1] = bh; + b.blocksize[2] = 1; + + ASTC_ReadBlockMode(&b); + + if (b.status == ASTC_VOID_HDR) + { //void extent + //Note: we don't validate the extents. + for (y = 0; y < bh; y++, out += stride) + for (x = 0; x < bw; x++) + { //hdr void extents already use fp16 + out[(x<<2)+0] = in[8] | (in[9]<<8); + out[(x<<2)+1] = in[10] | (in[11]<<8); + out[(x<<2)+2] = in[12] | (in[13]<<8); + out[(x<<2)+3] = in[14] | (in[15]<<8); + } + return; + } + if (b.status == ASTC_VOID_LDR) + { //void extent + //Note: we don't validate the extents. + for (y = 0; y < bh; y++, out += stride) + for (x = 0; x < bw; x++) + { + out[(x<<2)+0] = ASTC_GenHalffloat(0, in[8] | (in[9]<<8)); + out[(x<<2)+1] = ASTC_GenHalffloat(0, in[10] | (in[11]<<8)); + out[(x<<2)+2] = ASTC_GenHalffloat(0, in[12] | (in[13]<<8)); + out[(x<<2)+3] = ASTC_GenHalffloat(0, in[14] | (in[15]<<8)); + } + return; + } + + if (b.status == ASTC_OKAY) + ASTC_ReadPartitions(&b); + if (b.status == ASTC_OKAY) + ASTC_ReadEndpoints(&b); + + if (b.status == ASTC_OKAY) + { + int smallblock = (b.blocksize[0]*b.blocksize[1]*b.blocksize[2])<31; + int ds = (1024+b.blocksize[0]/2)/(b.blocksize[0]-1); + int dt = (1024+b.blocksize[1]/2)/(b.blocksize[1]-1); + int planes = 1<>6; + for (y = 0; y < bh; y++, out += stride) + { + t = ((dt*y)*(b.wcount[1]-1)+32)>>6; + for (x = 0; x < bw; x++) + { + p = &b.part[ASTC_ChoosePartition(b.partindex, x,y,0, b.partitions, smallblock)]; + s = ((ds*x)*(b.wcount[0]-1)+32)>>6; + w11 = ((s&0xf)*(t&0xf)+8) >> 4; + w10 = (t&0xf) - w11; + w01 = (s&0xf) - w11; + w00 = 16 - (s&0xf) - (t&0xf) + w11; + + v0 = (((s>>4))<>4))*wstride); + w = ( w00*b.weights[v0] + + w01*b.weights[v0+planes] + + w10*b.weights[v0+wstride] + + w11*b.weights[v0+planes+wstride] + 8) >> 4; + out[(x<<2)+0] = ASTC_GenHalffloat(p->hdr&1, ((64-w)*p->ep[0][0] + w*p->ep[1][0])>>6); + out[(x<<2)+1] = ASTC_GenHalffloat(p->hdr&1, ((64-w)*p->ep[0][1] + w*p->ep[1][1])>>6); + out[(x<<2)+2] = ASTC_GenHalffloat(p->hdr&1, ((64-w)*p->ep[0][2] + w*p->ep[1][2])>>6); + out[(x<<2)+3] = ASTC_GenHalffloat(p->hdr&8, ((64-w)*p->ep[0][3] + w*p->ep[1][3])>>6); + + if (b.dualplane) + { //dual planes has a second set of weights that override a single channel + v0++; + w = ( w00*b.weights[v0] + + w01*b.weights[v0+planes] + + w10*b.weights[v0+wstride] + + w11*b.weights[v0+planes+wstride] + 8) >> 4; + out[(x<<2)+b.ccs] = ASTC_GenHalffloat(p->hdr&(1<ep[0][b.ccs] + w*p->ep[1][b.ccs])>>6); + } + } + } + } + } + else + { + for (y = 0; y < bh; y++, out += stride) + for (x = 0; x < bw; x++) + { + out[(x<<2)+0] = 0;//0xf<<10; + out[(x<<2)+1] = 0; + out[(x<<2)+2] = 0;//0xf<<10; + out[(x<<2)+3] = 0xf<<10; + } + } +} +#endif diff --git a/engine/client/keys.c b/engine/client/keys.c index 35b60d1f9..3c0a92c31 100644 --- a/engine/client/keys.c +++ b/engine/client/keys.c @@ -673,8 +673,38 @@ qboolean Key_GetConsoleSelectionBox(console_t *con, int *sx, int *sy, int *ex, i if (con->buttonsdown == CB_SCROLL || con->buttonsdown == CB_SCROLL_R) { + float lineheight = Font_CharVHeight(font_console); //left-mouse. //scroll the console with the mouse. trigger links on release. + con->displayscroll += (con->mousecursor[1] - con->mousedown[1])/lineheight; + con->mousedown[1] = con->mousecursor[1]; + while (con->displayscroll > con->display->numlines) + { + if (con->display->older) + { + con->displayscroll -= con->display->numlines; + con->display = con->display->older; + } + else + { + con->displayscroll = con->display->numlines; + break; + } + } + while (con->displayscroll <= 0) + { + if (con->display->newer) + { + con->display = con->display->newer; + con->displayscroll += con->display->numlines; + } + else + { + con->displayscroll = 0; + break; + } + } + /* while (con->mousecursor[1] - con->mousedown[1] > 8 && con->display->older) { con->mousedown[1] += 8; @@ -685,7 +715,7 @@ qboolean Key_GetConsoleSelectionBox(console_t *con, int *sx, int *sy, int *ex, i con->mousedown[1] -= 8; con->display = con->display->newer; } - +*/ *sx = con->mousecursor[0]; *sy = con->mousecursor[1]; *ex = con->mousecursor[0]; @@ -1585,12 +1615,26 @@ qboolean Key_EntryLine(console_t *con, unsigned char **line, int lineoffset, int Sys_Clipboard_PasteText(CBT_SELECTION, Key_ConsolePaste, line); return true; } - if (((unicode=='V' || unicode=='v' || unicode==22) && ctrl) || (shift && key == K_INS)) + if (((unicode=='V' || unicode=='v' || unicode==22/*sync*/) && ctrl) || (shift && key == K_INS)) { //ctrl+v to paste from the windows-style clipboard. Sys_Clipboard_PasteText(CBT_CLIPBOARD, Key_ConsolePaste, line); return true; } + if ((unicode=='X' || unicode=='x' || unicode==24/*cancel*/) && ctrl) + { //cut - copy-to-clipboard-and-delete + Sys_SaveClipboard(CBT_CLIPBOARD, *line); + (*line)[lineoffset] = 0; + *linepos = strlen(*line); + return true; + } + if ((unicode=='U' || unicode=='u' || unicode==21/*nak*/) && ctrl) + { //clear line + (*line)[lineoffset] = 0; + *linepos = strlen(*line); + return true; + } + if (unicode < ' ') { //if the user is entering control codes, then the ctrl+foo mechanism is probably unsupported by the unicode input stuff, so give best-effort replacements. @@ -1820,14 +1864,16 @@ qboolean Key_Console (console_t *con, int key, unsigned int unicode) i = 8; if (!con->display) return true; - if (con->display == con->current) - i+=2; //skip over the blank input line, and extra so we actually move despite the addition of the ^^^^^ line +// if (con->display == con->current) +// i+=2; //skip over the blank input line, and extra so we actually move despite the addition of the ^^^^^ line if (con->display->older != NULL) { - while (i-->0) + con->displayscroll += i; + while (con->displayscroll >= con->display->numlines) { if (con->display->older == NULL) break; + con->displayscroll -= con->display->numlines; con->display = con->display->older; con->display->time = realtime; } @@ -1845,15 +1891,20 @@ qboolean Key_Console (console_t *con, int key, unsigned int unicode) return true; if (con->display->newer != NULL) { - while (i-->0) + con->displayscroll -= i; + while (con->displayscroll < 0) { if (con->display->newer == NULL) break; con->display = con->display->newer; con->display->time = realtime; + con->displayscroll += con->display->numlines; } if (con->display->newer && con->display->newer == con->current) + { con->display = con->current; + con->displayscroll = 0; + } return true; } } @@ -1862,6 +1913,7 @@ qboolean Key_Console (console_t *con, int key, unsigned int unicode) { if (con->display != con->oldest) { + con->displayscroll = 0; con->display = con->oldest; return true; } @@ -1871,6 +1923,7 @@ qboolean Key_Console (console_t *con, int key, unsigned int unicode) { if (con->display != con->current) { + con->displayscroll = 0; con->display = con->current; return true; } diff --git a/engine/client/m_download.c b/engine/client/m_download.c index 95f5f4ca0..788aef4a7 100644 --- a/engine/client/m_download.c +++ b/engine/client/m_download.c @@ -2,6 +2,7 @@ //provides both a package manager and downloads menu. //FIXME: block downloads of exe/dll/so/etc if not an https url (even if inside zips). also block such files from package lists over http. #include "quakedef.h" +#include "shader.h" #ifdef PACKAGEMANAGER #if !defined(NOBUILTINMENUS) && !defined(SERVERONLY) @@ -161,15 +162,16 @@ typedef struct package_s { struct packagedep_s *next; enum { - DEP_CONFLICT, + DEP_CONFLICT, //don't install if we have the named package installed. DEP_FILECONFLICT, //don't install if this file already exists. - DEP_REQUIRE, - DEP_RECOMMEND, //like depend, but uninstalling will not bubble. - DEP_SUGGEST, //like recommend, but will not force install (ie: only prevents auto-uninstall) + DEP_REQUIRE, //don't install unless we have the named package installed. + DEP_RECOMMEND, //like depend, but uninstalling will not bubble. + DEP_SUGGEST, //like recommend, but will not force install (ie: only prevents auto-uninstall) + DEP_NEEDFEATURE, //requires a specific feature to be available (typically controlled via a cvar) // DEP_MIRROR, // DEP_FAILEDMIRROR, - DEP_FILE + DEP_FILE //a file that will be installed } dtype; char name[1]; } *deps; @@ -549,6 +551,57 @@ static void PM_InsertPackage(package_t *p) numpackages++; } +static qboolean PM_CheckFeature(const char *feature, const char **featurename, const char **concommand) +{ +#ifdef HAVE_CLIENT + extern cvar_t r_replacemodels; +#endif + *featurename = NULL; + *concommand = NULL; +#ifdef HAVE_CLIENT + //check for compressed texture formats, to warn when not supported. + if (!strcmp(feature, "bc1") || !strcmp(feature, "bc2") || !strcmp(feature, "bc3") || !strcmp(feature, "s3tc")) + return *featurename="S3 Texture Compression", sh_config.hw_bc>=1; + if (!strcmp(feature, "bc4") || !strcmp(feature, "bc5") || !strcmp(feature, "rgtc")) + return *featurename="Red/Green Texture Compression", sh_config.hw_bc>=2; + if (!strcmp(feature, "bc6") || !strcmp(feature, "bc7") || !strcmp(feature, "bptc")) + return *featurename="Block Partitioned Texture Compression", sh_config.hw_bc>=3; + if (!strcmp(feature, "etc1")) + return *featurename="Ericson Texture Compression, Original", sh_config.hw_etc>=1; + if (!strcmp(feature, "etc2") || !strcmp(feature, "eac")) + return *featurename="Ericson Texture Compression, Revision 2", sh_config.hw_etc>=2; + if (!strcmp(feature, "astcldr") || !strcmp(feature, "astc")) + return *featurename="Adaptive Scalable Texture Compression (LDR)", sh_config.hw_astc>=1; + if (!strcmp(feature, "astchdr")) + return *featurename="Adaptive Scalable Texture Compression (HDR)", sh_config.hw_astc>=2; + + if (!strcmp(feature, "24bit")) + return *featurename="24bit Textures", *concommand="seta gl_load24bit 1\n", gl_load24bit.ival; + if (!strcmp(feature, "md3")) + return *featurename="Replacement Models", *concommand="seta r_replacemodels md3 md2\n", !!strstr(r_replacemodels.string, "md3"); + if (!strcmp(feature, "rtlights")) + return *featurename="Realtime Dynamic Lights", *concommand="seta r_shadow_realtime_dlight 1\n", r_shadow_realtime_dlight.ival||r_shadow_realtime_world.ival; + if (!strcmp(feature, "rtworld")) + return *featurename="Realtime World Lights", *concommand="seta r_shadow_realtime_dlight 1\nseta r_shadow_realtime_world 1\n", r_shadow_realtime_world.ival; +#endif + + return false; +} +static qboolean PM_CheckPackageFeatures(package_t *p) +{ + struct packagedep_s *dep; + const char *featname, *enablecmd; + + for (dep = p->deps; dep; dep = dep->next) + { + if (dep->dtype == DEP_NEEDFEATURE) + { + if (!PM_CheckFeature(dep->name, &featname, &enablecmd)) + return false; + } + } + return true; +} static qboolean PM_CheckFile(const char *filename, enum fs_relative base) { @@ -916,6 +969,8 @@ static qboolean PM_ParsePackageList(vfsfile_t *f, int parseflags, const char *ur PM_AddDep(p, DEP_RECOMMEND, val); else if (!strcmp(key, "suggest")) PM_AddDep(p, DEP_SUGGEST, val); + else if (!strcmp(key, "need")) + PM_AddDep(p, DEP_NEEDFEATURE, val); else if (!strcmp(key, "test")) flags |= DPF_TESTING; else if (!strcmp(key, "stale") && version==2) @@ -1486,7 +1541,12 @@ static void PM_MarkPackage(package_t *package, unsigned int markflag) { d = PM_FindPackage(dep->name); if (d) - PM_MarkPackage(d, DPF_AUTOMARKED); + { + if (dep->dtype == DEP_RECOMMEND && !PM_CheckPackageFeatures(d)) + Con_DPrintf("Skipping recommendation \"%s\"\n", dep->name); + else + PM_MarkPackage(d, DPF_AUTOMARKED); + } else Con_DPrintf("Couldn't find dependancy \"%s\"\n", dep->name); } @@ -1995,6 +2055,11 @@ static void PM_WriteInstalledPackages(void) Q_strncatz(buf, " ", sizeof(buf)); COM_QuotedConcat(va("recommend=%s", dep->name), buf, sizeof(buf)); } + else if (dep->dtype == DEP_NEEDFEATURE) + { + Q_strncatz(buf, " ", sizeof(buf)); + COM_QuotedConcat(va("need=%s", dep->name), buf, sizeof(buf)); + } } if (p->flags & DPF_TESTING) @@ -2025,6 +2090,31 @@ static void PM_WriteInstalledPackages(void) } } +//package has been downloaded and installed, but some packages need to be enabled +//(plugins might have other dll dependancies, so this can only happen AFTER the entire package was extracted) +static void PM_PackageEnabled(package_t *p) +{ + char ext[8]; + struct packagedep_s *dep; + FS_FlushFSHashFull(); + for (dep = p->deps; dep; dep = dep->next) + { + if (dep->dtype != DEP_FILE) + continue; + COM_FileExtension(dep->name, ext, sizeof(ext)); + if (!stricmp(ext, "pak") || !stricmp(ext, "pk3")) + FS_ReloadPackFiles(); +#ifdef PLUGINS + if ((p->flags & DPF_PLUGIN) && !Q_strncasecmp(dep->name, PLUGINPREFIX, strlen(PLUGINPREFIX))) + Cmd_ExecuteString(va("plug_load %s\n", dep->name), RESTRICT_LOCAL); +#endif +#ifdef MENU_DAT + if (!Q_strcasecmp(dep->name, "menu.dat")) + Cmd_ExecuteString("menu_restart\n", RESTRICT_LOCAL); +#endif + } +} + #ifdef WEBCLIENT //callback from PM_Download_Got, extracts each file from an archive static int QDECL PM_ExtractFiles(const char *fname, qofs_t fsize, time_t mtime, void *parm, searchpathfuncs_t *spath) @@ -2057,31 +2147,6 @@ static int QDECL PM_ExtractFiles(const char *fname, qofs_t fsize, time_t mtime, return 1; } -//package has been downloaded and installed, but some packages need to be enabled -//(plugins might have other dll dependancies, so this can only happen AFTER the entire package was extracted) -static void PM_PackageEnabled(package_t *p) -{ - char ext[8]; - struct packagedep_s *dep; - FS_FlushFSHashFull(); - for (dep = p->deps; dep; dep = dep->next) - { - if (dep->dtype != DEP_FILE) - continue; - COM_FileExtension(dep->name, ext, sizeof(ext)); - if (!stricmp(ext, "pak") || !stricmp(ext, "pk3")) - FS_ReloadPackFiles(); -#ifdef PLUGINS - if ((p->flags & DPF_PLUGIN) && !Q_strncasecmp(dep->name, PLUGINPREFIX, strlen(PLUGINPREFIX))) - Cmd_ExecuteString(va("plug_load %s\n", dep->name), RESTRICT_LOCAL); -#endif -#ifdef MENU_DAT - if (!Q_strcasecmp(dep->name, "menu.dat")) - Cmd_ExecuteString("menu_restart\n", RESTRICT_LOCAL); -#endif - } -} - static void PM_StartADownload(void); //callback from PM_StartADownload static void PM_Download_Got(struct dl_download *dl) @@ -2334,10 +2399,10 @@ int PM_IsApplying(qboolean listsonly) return count; } +#ifdef WEBCLIENT //looks for the next package that needs downloading, and grabs it static void PM_StartADownload(void) { -#ifdef WEBCLIENT vfsfile_t *tmpfile; char *temp; package_t *p; @@ -2466,8 +2531,8 @@ static void PM_StartADownload(void) //clear the updating flag once there's no more activity needed pkg_updating = downloading; -#endif } +#endif //'just' starts doing all the things needed to remove/install selected packages void PM_ApplyChanges(void) { @@ -2611,8 +2676,45 @@ void PM_ApplyChanges(void) if ((p->flags&DPF_MARKED) && !(p->flags&DPF_ENABLED) && !p->download) p->trymirrors = ~0u; } -#endif PM_StartADownload(); //and try to do those downloads. +#else + for (p = availablepackages; p; p=p->next) + { + if ((p->flags&DPF_MARKED) && !(p->flags&DPF_ENABLED)) + { //flagged for a (re?)download + int i; + struct packagedep_s *dep; + for (i = 0; i < countof(p->mirror); i++) + if (p->mirror[i]) + break; + for (dep = p->deps; dep; dep=dep->next) + if (dep->dtype == DEP_FILE) + break; + if (!dep && i == countof(p->mirror)) + { //this appears to be a meta package with no download + //just directly install it. + p->flags &= ~(DPF_NATIVE|DPF_CACHED|DPF_CORRUPT); + p->flags |= DPF_ENABLED; + + Con_Printf("Enabled meta package %s\n", p->name); + PM_WriteInstalledPackages(); + PM_PackageEnabled(p); + } + + if ((p->flags & DPF_PRESENT) && !PM_PurgeOnDisable(p)) + { //its in our cache directory, so lets just use that + p->flags |= DPF_ENABLED; + + Con_Printf("Enabled cached package %s\n", p->name); + PM_WriteInstalledPackages(); + PM_PackageEnabled(p); + continue; + } + else + p->flags &= ~DPF_MARKED; + } + } +#endif } #if defined(M_Menu_Prompt) || defined(SERVERONLY) @@ -3202,8 +3304,12 @@ static void MD_Draw (int x, int y, struct menucustom_s *c, struct emenu_s *m) if (p->flags & DPF_TESTING) //hide testing updates n = va("^h%s", n); -// if (!(p->flags & (DPF_ENABLED|DPF_MARKED|DPF_PRESENT)) -// continue; + + if (!PM_CheckPackageFeatures(p)) + Draw_FunStringWidth(0, y, "!", x+8, true, true); + +// if (!(p->flags & (DPF_ENABLED|DPF_MARKED|DPF_PRESENT)) +// continue; // if (&m->selecteditem->common == &c->common) // Draw_AltFunString (x+48, y, n); @@ -3404,6 +3510,7 @@ static int MD_AddItemsToDownloadMenu(emenu_t *m, int y, const char *pathprefix) char *slash; menuoption_t *mo; int prefixlen = strlen(pathprefix); + struct packagedep_s *dep; //add all packages in this dir for (p = availablepackages; p; p = p->next) @@ -3420,10 +3527,26 @@ static int MD_AddItemsToDownloadMenu(emenu_t *m, int y, const char *pathprefix) desc = va("^aauthor: ^a%s\n^alicense: ^a%s\n^awebsite: ^a%s\n%s", p->author?p->author:"^hUnknown^h", p->license?p->license:"^hUnknown^h", p->website?p->website:"^hUnknown^h", p->description); else desc = p->description; + + for (dep = p->deps; dep; dep = dep->next) + { + if (dep->dtype == DEP_NEEDFEATURE) + { + const char *featname, *enablecmd; + if (!PM_CheckFeature(dep->name, &featname, &enablecmd)) + { + if (enablecmd) + desc = va("^aDisabled: ^a%s\n%s", featname, desc); + else + desc = va("^aUnavailable: ^a%s\n%s", featname, desc); + } + } + } + c = MC_AddCustom(m, 0, y, p, downloadablessequence, desc); c->draw = MD_Draw; c->key = MD_Key; - c->common.width = 320; + c->common.width = 320-16; c->common.height = 8; y += 8; diff --git a/engine/client/m_items.c b/engine/client/m_items.c index f9e5ad2ce..751c6900e 100644 --- a/engine/client/m_items.c +++ b/engine/client/m_items.c @@ -479,7 +479,7 @@ static void MenuDrawItems(int xpos, int ypos, menuoption_t *option, emenu_t *men if (option->common.ishidden) continue; - if (&menu->menu == topmenu && menu->mouseitem == option) + if (&menu->menu == topmenu && menu->mouseitem == option && option->common.type != mt_frameend) { float alphamax = 0.5, alphamin = 0.2; R2D_ImageColours(.5,.4,0,(sin(realtime*2)+1)*0.5*(alphamax-alphamin)+alphamin); diff --git a/engine/client/merged.h b/engine/client/merged.h index 6d9c907c5..c50700fb4 100644 --- a/engine/client/merged.h +++ b/engine/client/merged.h @@ -241,7 +241,7 @@ typedef struct image_s int status; //TEX_ unsigned int flags; struct image_s *next; - struct image_s *prev; +// struct image_s *prev; struct image_s *aliasof; union { @@ -371,16 +371,16 @@ typedef struct typedef struct texnums_s { char mapname[MAX_QPATH]; //the 'official' name of the diffusemap. used to generate filenames for other textures. - texid_t base; //regular diffuse texture. may have alpha if surface is transparent + texid_t base; //regular diffuse texture. may have alpha if surface is transparent. texid_t bump; //normalmap. height values packed in alpha. - texid_t specular; //specular lighting values. - texid_t upperoverlay; //diffuse texture for the upper body(shirt colour). no alpha channel. added to base.rgb - texid_t loweroverlay; //diffuse texture for the lower body(trouser colour). no alpha channel. added to base.rgb + texid_t specular; //specular lighting values. alpha contains exponent multiplier + texid_t upperoverlay; //diffuse texture for the upper body(shirt colour). no alpha channel. added to base.rgb. ideally an l8 texture + texid_t loweroverlay; //diffuse texture for the lower body(trouser colour). no alpha channel. added to base.rgb. ideally an l8 texture texid_t paletted; //8bit paletted data, just because. - texid_t fullbright; - texid_t reflectcube; - texid_t reflectmask; - texid_t displacement; + texid_t fullbright; //emissive texture. alpha should be 1. + texid_t reflectcube; //for fake reflections + texid_t reflectmask; //defines how reflective it is (for cubemap reflections) + texid_t displacement; //alternative to bump.a, eg R16[F] for offsetmapping or tessellation texid_t occlusion; //occlusion map... //the material's pushconstants. vulkan guarentees only 128 bytes. so 8 vec4s. note that lmscales should want 4 of them... diff --git a/engine/client/pr_csqc.c b/engine/client/pr_csqc.c index f725b306d..2201dfe17 100644 --- a/engine/client/pr_csqc.c +++ b/engine/client/pr_csqc.c @@ -727,7 +727,8 @@ static void QCBUILTIN PF_cs_remove (pubprogfuncs_t *prinst, struct globalvars_s return; } - pe->DelinkTrailstate(&ed->trailstate); + if (pe) + pe->DelinkTrailstate(&ed->trailstate); World_UnlinkEdict((wedict_t*)ed); ED_Free (prinst, (void*)ed); } @@ -7362,7 +7363,7 @@ void ASMCALL CSQC_ThinkTimeOp(pubprogfuncs_t *progs, edict_t *ed, float var) vars->nextthink = *w->g.time+var; } -pbool PDECL CSQC_CheckHeaderCrc(pubprogfuncs_t *progs, progsnum_t num, int crc) +pbool PDECL CSQC_CheckHeaderCrc(pubprogfuncs_t *progs, progsnum_t num, int crc, const char *filename) { if (!num) { diff --git a/engine/client/pr_menu.c b/engine/client/pr_menu.c index 5909bc583..99c529fe8 100644 --- a/engine/client/pr_menu.c +++ b/engine/client/pr_menu.c @@ -2686,11 +2686,11 @@ void MP_CvarChanged(cvar_t *var) } } -pbool PDECL Menu_CheckHeaderCrc(pubprogfuncs_t *inst, progsnum_t idx, int crc) +pbool PDECL Menu_CheckHeaderCrc(pubprogfuncs_t *inst, progsnum_t idx, int crc, const char *filename) { if (crc == 10020) return true; //its okay - Con_Printf("progs crc is invalid for menuqc\n"); + Con_Printf("progs crc is invalid for %s\n", filename); return false; } diff --git a/engine/client/r_surf.c b/engine/client/r_surf.c index 265a41d5e..91b41bc98 100644 --- a/engine/client/r_surf.c +++ b/engine/client/r_surf.c @@ -3686,7 +3686,7 @@ uploadfmt_t Surf_LightmapMode(model_t *model) fmt = PTI_RGBA32F; else if (sh_config.texfmt[PTI_A2BGR10] && rgb) fmt = PTI_A2BGR10; - else if (sh_config.texfmt[PTI_L8] && !rgb && !r_deluxemapping) + else if (sh_config.texfmt[PTI_L8] && !rgb && !r_deluxemapping && r_dynamic.ival<=0) fmt = PTI_L8; else if (sh_config.texfmt[PTI_BGRX8]) fmt = PTI_BGRX8; diff --git a/engine/client/render.h b/engine/client/render.h index d9e773b98..524ba3ffb 100644 --- a/engine/client/render.h +++ b/engine/client/render.h @@ -423,6 +423,7 @@ enum imageflags IF_NOGAMMA = 1<<9, /*do not apply texture-based gamma*/ IF_3DMAP = 1<<10, /*waning - don't test directly*/ IF_CUBEMAP = 1<<11, /*waning - don't test directly*/ + IF_2DARRAY = IF_3DMAP|IF_CUBEMAP, IF_TEXTYPE = (1<<10) | (1<<11), /*0=2d, 1=3d, 2=cubeface, 3=2d array texture*/ IF_TEXTYPESHIFT = 10, /*0=2d, 1=3d, 2-7=cubeface*/ IF_MIPCAP = 1<<12, //allow the use of d_mipcap @@ -593,7 +594,7 @@ void RQ_Shutdown(void); void WritePCXfile (const char *filename, enum fs_relative fsroot, qbyte *data, int width, int height, int rowbytes, qbyte *palette, qboolean upload); //data is 8bit. qbyte *ReadPCXFile(qbyte *buf, int length, int *width, int *height); -qbyte *ReadTargaFile(qbyte *buf, int length, int *width, int *height, uploadfmt_t *format, qboolean greyonly, uploadfmt_t forceformat); +void *ReadTargaFile(qbyte *buf, int length, int *width, int *height, uploadfmt_t *format, qboolean greyonly, uploadfmt_t forceformat); qbyte *ReadJPEGFile(qbyte *infile, int length, int *width, int *height); qbyte *ReadPNGFile(const char *fname, qbyte *buf, int length, int *width, int *height, uploadfmt_t *format); qbyte *ReadPCXPalette(qbyte *buf, int len, qbyte *out); diff --git a/engine/client/renderer.c b/engine/client/renderer.c index f03a0ba6d..5915cba9d 100644 --- a/engine/client/renderer.c +++ b/engine/client/renderer.c @@ -36,7 +36,6 @@ qboolean vid_isfullscreen; #define GLRENDEREROPTIONS "GL Renderer Options" //fixme: often used for generic cvars that apply to more than just gl... #define D3DRENDEREROPTIONS "D3D Renderer Options" -#define VKRENDEREROPTIONS "Vulkan-Specific Renderer Options" unsigned int d_8to24rgbtable[256]; unsigned int d_8to24srgbtable[256]; @@ -239,7 +238,7 @@ cvar_t scr_allowsnap = CVARF ("scr_allowsnap", "1", CVAR_NOTFROMSERVER); cvar_t scr_centersbar = CVAR ("scr_centersbar", "2"); cvar_t scr_centertime = CVAR ("scr_centertime", "2"); -cvar_t scr_logcenterprint = CVARD ("con_logcenterprint", "1", "Specifies whether to print centerprints on the console.\n0: never\n1: single-player or coop only.\n2: always.\n"); +cvar_t scr_logcenterprint = CVARD ("con_logcenterprint", "1", "Specifies whether to print centerprints on the console.\n0: never\n1: single-player or coop only.\n2: always."); cvar_t scr_conalpha = CVARC ("scr_conalpha", "0.7", Cvar_Limiter_ZeroToOne_Callback); cvar_t scr_consize = CVAR ("scr_consize", "0.5"); @@ -455,7 +454,7 @@ cvar_t r_glsl_offsetmapping_reliefmapping = CVARFD("r_glsl_offsetmapping_reliefm cvar_t r_glsl_turbscale_reflect = CVARFD ("r_glsl_turbscale_reflect", "1", CVAR_ARCHIVE, "Controls the strength of the water reflection ripples (used by the altwater glsl code)."); cvar_t r_glsl_turbscale_refract = CVARFD ("r_glsl_turbscale_refract", "1", CVAR_ARCHIVE, "Controls the strength of the underwater ripples (used by the altwater glsl code)."); -cvar_t r_fastturbcolour = CVARFD ("r_fastturbcolour", "0.1 0.2 0.3", CVAR_ARCHIVE, "The colour to use for water surfaces draw with r_waterstyle 0.\n"); +cvar_t r_fastturbcolour = CVARFD ("r_fastturbcolour", "0.1 0.2 0.3", CVAR_ARCHIVE, "The colour to use for water surfaces draw with r_waterstyle 0."); cvar_t r_waterstyle = CVARFD ("r_waterstyle", "1", CVAR_ARCHIVE|CVAR_SHADERSYSTEM, "Changes how water, and teleporters are drawn. Possible values are:\n0: fastturb-style block colour.\n1: regular q1-style water.\n2: refraction(ripply and transparent)\n3: refraction with reflection at an angle\n4: ripplemapped without reflections (requires particle effects)\n5: ripples+reflections"); cvar_t r_slimestyle = CVARFD ("r_slimestyle", "", CVAR_ARCHIVE|CVAR_SHADERSYSTEM, "See r_waterstyle, but affects only slime. If empty, defers to r_waterstyle."); cvar_t r_lavastyle = CVARFD ("r_lavastyle", "1", CVAR_ARCHIVE|CVAR_SHADERSYSTEM, "See r_waterstyle, but affects only lava. If empty, defers to r_waterstyle."); @@ -477,21 +476,6 @@ extern cvar_t gl_dither; cvar_t gl_screenangle = CVAR("gl_screenangle", "0"); #endif -#ifdef VKQUAKE -cvar_t vk_stagingbuffers = CVARFD ("vk_stagingbuffers", "", CVAR_RENDERERLATCH, "Configures which dynamic buffers are copied into gpu memory for rendering, instead of reading from shared memory. Empty for default settings.\nAccepted chars are u(niform), e(lements), v(ertex), 0(none)."); -cvar_t vk_submissionthread = CVARD ("vk_submissionthread", "", "Execute submits+presents on a thread dedicated to executing them. This may be a significant speedup on certain drivers."); -cvar_t vk_debug = CVARFD("vk_debug", "0", CVAR_VIDEOLATCH, "Register a debug handler to display driver/layer messages. 2 enables the standard validation layers."); -cvar_t vk_dualqueue = CVARFD("vk_dualqueue", "", CVAR_VIDEOLATCH, "Attempt to use a separate queue for presentation. Blank for default."); -cvar_t vk_busywait = CVARD ("vk_busywait", "", "Force busy waiting until the GPU finishes doing its thing."); -cvar_t vk_waitfence = CVARD ("vk_waitfence", "", "Waits on fences, instead of semaphores. This is more likely to result in gpu stalls while the cpu waits."); -cvar_t vk_usememorypools = CVARFD("vk_usememorypools", "", CVAR_VIDEOLATCH, "Allocates memory pools for sub allocations. Vulkan has a limit to the number of memory allocations allowed so this should always be enabled, however at this time FTE is unable to reclaim pool memory, and would require periodic vid_restarts to flush them."); -cvar_t vk_nv_glsl_shader = CVARFD("vk_loadglsl", "", CVAR_VIDEOLATCH, "Enable direct loading of glsl, where supported by drivers. Do not use in combination with vk_debug 2 (vk_debug should be 1 if you want to see any glsl compile errors). Don't forget to do a vid_restart after."); -cvar_t vk_khr_get_memory_requirements2 = CVARFD("vk_khr_get_memory_requirements2", "", CVAR_VIDEOLATCH, "Enable extended memory info querires"); -cvar_t vk_khr_dedicated_allocation = CVARFD("vk_khr_dedicated_allocation", "", CVAR_VIDEOLATCH, "Flag vulkan memory allocations as dedicated, where applicable."); -cvar_t vk_khr_push_descriptor = CVARFD("vk_khr_push_descriptor", "", CVAR_VIDEOLATCH, "Enables better descriptor streaming."); -cvar_t vk_amd_rasterization_order = CVARFD("vk_amd_rasterization_order", "", CVAR_VIDEOLATCH, "Enables the use of relaxed rasterization ordering, for a small speedup at the minor risk of a little zfighting."); -#endif - #ifdef D3D9QUAKE cvar_t d3d9_hlsl = CVAR("d3d_hlsl", "1"); #endif @@ -506,6 +490,8 @@ void GLD3DRenderer_Init(void) #endif #if defined(GLQUAKE) +extern cvar_t gl_blacklist_texture_compression; +extern cvar_t gl_blacklist_generatemipmap; void GLRenderer_Init(void) { //gl-specific video vars @@ -567,6 +553,8 @@ void GLRenderer_Init(void) Cvar_Register (&r_shaderblobs, GLRENDEREROPTIONS); Cvar_Register (&gl_compress, GLRENDEREROPTIONS); + Cvar_Register (&gl_blacklist_texture_compression, "gl blacklists"); + Cvar_Register (&gl_blacklist_generatemipmap, "gl blacklists"); // Cvar_Register (&gl_detail, GRAPHICALNICETIES); // Cvar_Register (&gl_detailscale, GRAPHICALNICETIES); Cvar_Register (&gl_overbright, GRAPHICALNICETIES); @@ -1023,19 +1011,7 @@ void Renderer_Init(void) Cvar_Register (&dpcompat_nopremulpics, GLRENDEREROPTIONS); #endif #ifdef VKQUAKE - Cvar_Register (&vk_stagingbuffers, VKRENDEREROPTIONS); - Cvar_Register (&vk_submissionthread, VKRENDEREROPTIONS); - Cvar_Register (&vk_debug, VKRENDEREROPTIONS); - Cvar_Register (&vk_dualqueue, VKRENDEREROPTIONS); - Cvar_Register (&vk_busywait, VKRENDEREROPTIONS); - Cvar_Register (&vk_waitfence, VKRENDEREROPTIONS); - Cvar_Register (&vk_usememorypools, VKRENDEREROPTIONS); - - Cvar_Register (&vk_nv_glsl_shader, VKRENDEREROPTIONS); - Cvar_Register (&vk_khr_get_memory_requirements2,VKRENDEREROPTIONS); - Cvar_Register (&vk_khr_dedicated_allocation,VKRENDEREROPTIONS); - Cvar_Register (&vk_khr_push_descriptor, VKRENDEREROPTIONS); - Cvar_Register (&vk_amd_rasterization_order, VKRENDEREROPTIONS); + VK_RegisterVulkanCvars(); #endif // misc @@ -1870,6 +1846,7 @@ void R_ReloadRenderer_f (void) BZ_Free(portalblob); } #endif + Con_DPrintf("vid_reload time: %f\n", Sys_DoubleTime() - time); } static int R_PriorityForRenderer(rendererinfo_t *r) diff --git a/engine/client/screen.h b/engine/client/screen.h index da4cf8e1e..0986c0152 100644 --- a/engine/client/screen.h +++ b/engine/client/screen.h @@ -115,7 +115,7 @@ typedef enum uploadfmt //floating point formats PTI_R16F, PTI_R32F, - PTI_RGBA16F, //consider using e5bgr9 + PTI_RGBA16F, //consider using e5bgr9 or bc6/astc PTI_RGBA32F, //usually overkill //packed/misaligned formats: these are specified in native endian order (high bits listed first because that's how things are represented in hex), so may need byte swapping... PTI_A2BGR10, //mostly for rendertargets, might also be useful for overbight lightmaps. @@ -126,63 +126,79 @@ typedef enum uploadfmt PTI_RGBA5551, //16bit alpha format (gl). PTI_ARGB1555, //16bit alpha format (d3d). //(desktop/tegra) compressed formats - PTI_BC1_RGB, - PTI_BC1_RGB_SRGB, - PTI_BC1_RGBA, - PTI_BC1_RGBA_SRGB, - PTI_BC2_RGBA, - PTI_BC2_RGBA_SRGB, - PTI_BC3_RGBA, //maybe add a bc3 normalmapswizzle type for d3d9? - PTI_BC3_RGBA_SRGB, - PTI_BC4_R8, //greyscale, kinda - PTI_BC4_R8_SNORM, - PTI_BC5_RG8, //useful for normalmaps - PTI_BC5_RG8_SNORM, //useful for normalmaps - PTI_BC6_RGB_UFLOAT, //unsigned (half) floats! - PTI_BC6_RGB_SFLOAT, //signed (half) floats! - PTI_BC7_RGBA, //multimode compression, using as many bits as bc2/bc3 - PTI_BC7_RGBA_SRGB, + PTI_BC1_RGB, /*4bpp*/ + PTI_BC1_RGB_SRGB, /*4bpp*/ + PTI_BC1_RGBA, /*4bpp*/ + PTI_BC1_RGBA_SRGB, /*4bpp*/ + PTI_BC2_RGBA, /*8bpp*/ + PTI_BC2_RGBA_SRGB, /*8bpp*/ + PTI_BC3_RGBA, /*8bpp*/ //maybe add a bc3 normalmapswizzle type for d3d9? + PTI_BC3_RGBA_SRGB, /*8bpp*/ + PTI_BC4_R8, /*4bpp*/ //greyscale, kinda + PTI_BC4_R8_SNORM, /*4bpp*/ + PTI_BC5_RG8, /*8bpp*/ //useful for normalmaps + PTI_BC5_RG8_SNORM, /*8bpp*/ //useful for normalmaps + PTI_BC6_RGB_UFLOAT, /*8bpp*/ //unsigned (half) floats! + PTI_BC6_RGB_SFLOAT, /*8bpp*/ //signed (half) floats! + PTI_BC7_RGBA, /*8bpp*/ //multimode compression, using as many bits as bc2/bc3 + PTI_BC7_RGBA_SRGB, /*8bpp*/ //(mobile/intel) compressed formats - PTI_ETC1_RGB8, //limited form - PTI_ETC2_RGB8, //extended form - PTI_ETC2_RGB8A1, - PTI_ETC2_RGB8A8, - PTI_ETC2_RGB8_SRGB, - PTI_ETC2_RGB8A1_SRGB, - PTI_ETC2_RGB8A8_SRGB, - PTI_EAC_R11, //might be useful for overlays, with swizzles. - PTI_EAC_R11_SNORM, //no idea what this might be used for, whatever - PTI_EAC_RG11, //useful for normalmaps (calculate blue) - PTI_EAC_RG11_SNORM, //useful for normalmaps (calculate blue) - //astc... zomg - PTI_ASTC_4X4, + PTI_ETC1_RGB8, /*4bpp*/ //limited form + PTI_ETC2_RGB8, /*4bpp*/ //extended form + PTI_ETC2_RGB8A1, /*4bpp*/ + PTI_ETC2_RGB8A8, /*8bpp*/ + PTI_ETC2_RGB8_SRGB, /*4bpp*/ + PTI_ETC2_RGB8A1_SRGB,/*4bpp*/ + PTI_ETC2_RGB8A8_SRGB,/*8bpp*/ + PTI_EAC_R11, /*4bpp*/ //might be useful for overlays, with swizzles. + PTI_EAC_R11_SNORM, /*4bpp*/ //no idea what this might be used for, whatever + PTI_EAC_RG11, /*8bpp*/ //useful for normalmaps (calculate blue) + PTI_EAC_RG11_SNORM, /*8bpp*/ //useful for normalmaps (calculate blue) + //astc... zomg. + PTI_ASTC_4X4_LDR, /*8bpp*/ //ldr/srgb/hdr formats are technically all the same. + PTI_ASTC_5X4_LDR, /*6.40*/ //srgb formats are different because of an extra srgb lookup step + PTI_ASTC_5X5_LDR, /*5.12*/ //ldr formats are identical to hdr except for the extended colour modes disabled. + PTI_ASTC_6X5_LDR, /*4.17*/ + PTI_ASTC_6X6_LDR, /*3.56*/ + PTI_ASTC_8X5_LDR, /*3.20*/ + PTI_ASTC_8X6_LDR, /*2.67*/ + PTI_ASTC_10X5_LDR, /*2.56*/ + PTI_ASTC_10X6_LDR, /*2.13*/ + PTI_ASTC_8X8_LDR, /*2bpp*/ + PTI_ASTC_10X8_LDR, /*1.60*/ + PTI_ASTC_10X10_LDR, /*1.28*/ + PTI_ASTC_12X10_LDR, /*1.07*/ + PTI_ASTC_12X12_LDR, /*0.89*/ PTI_ASTC_4X4_SRGB, - PTI_ASTC_5X4, PTI_ASTC_5X4_SRGB, - PTI_ASTC_5X5, PTI_ASTC_5X5_SRGB, - PTI_ASTC_6X5, PTI_ASTC_6X5_SRGB, - PTI_ASTC_6X6, PTI_ASTC_6X6_SRGB, - PTI_ASTC_8X5, PTI_ASTC_8X5_SRGB, - PTI_ASTC_8X6, PTI_ASTC_8X6_SRGB, - PTI_ASTC_10X5, PTI_ASTC_10X5_SRGB, - PTI_ASTC_10X6, PTI_ASTC_10X6_SRGB, - PTI_ASTC_8X8, PTI_ASTC_8X8_SRGB, - PTI_ASTC_10X8, PTI_ASTC_10X8_SRGB, - PTI_ASTC_10X10, PTI_ASTC_10X10_SRGB, - PTI_ASTC_12X10, PTI_ASTC_12X10_SRGB, - PTI_ASTC_12X12, PTI_ASTC_12X12_SRGB, + PTI_ASTC_4X4_HDR, //these are not strictly necessary, and are likely to be treated identically to the ldr versions, but they may use extra features that the hardware does not support + PTI_ASTC_5X4_HDR, + PTI_ASTC_5X5_HDR, + PTI_ASTC_6X5_HDR, + PTI_ASTC_6X6_HDR, + PTI_ASTC_8X5_HDR, + PTI_ASTC_8X6_HDR, + PTI_ASTC_10X5_HDR, + PTI_ASTC_10X6_HDR, + PTI_ASTC_8X8_HDR, + PTI_ASTC_10X8_HDR, + PTI_ASTC_10X10_HDR, + PTI_ASTC_12X10_HDR, + PTI_ASTC_12X12_HDR, +#define PTI_ASTC_FIRST PTI_ASTC_4X4_LDR +#define PTI_ASTC_LAST PTI_ASTC_12X12_HDR //depth formats PTI_DEPTH16, @@ -200,12 +216,12 @@ typedef enum uploadfmt TF_TRANS8, /*8bit quake-palette image, index 255=transparent*/ TF_TRANS8_FULLBRIGHT, /*fullbright 8 - fullbright texels have alpha 255, everything else 0*/ TF_HEIGHT8, /*image data is greyscale, convert to a normalmap and load that, uploaded alpha contains the original heights*/ - TF_HEIGHT8PAL, /*source data is palette values rather than actual heights, generate a fallback heightmap*/ + TF_HEIGHT8PAL, /*source data is palette values rather than actual heights, generate a fallback heightmap. actual palette is ignored...*/ TF_H2_T7G1, /*8bit data, odd indexes give greyscale transparence*/ TF_H2_TRANS8_0, /*8bit data, 0 is transparent, not 255*/ TF_H2_T4A4, /*8bit data, weird packing*/ - PTI_LLLX8, /*RGB data where the RGB values were all the same. we can convert to L8 to use less memory (common with shirt/pants/reflection)*/ + PTI_LLLX8, /*RGBX data where the RGB values were all the same. we can convert to L8 to use less memory (common with shirt/pants/reflection)*/ PTI_LLLA8, /*RGBA data where the RGB values were all the same. we can convert to LA8 to use less memory (common with gloss)*/ /*this block requires an explicit (separate) palette*/ diff --git a/engine/client/snd_alsa.c b/engine/client/snd_alsa.c index 8640e41b1..9d956cde0 100755 --- a/engine/client/snd_alsa.c +++ b/engine/client/snd_alsa.c @@ -202,6 +202,46 @@ static qboolean Alsa_InitAlsa(void) { static qboolean tried; static qboolean alsaworks; + + static dllfunction_t funcs[] = + { + {(void**)&psnd_pcm_open, "snd_pcm_open"}, + {(void**)&psnd_pcm_close, "snd_pcm_close"}, + {(void**)&psnd_config_update_free_global, "snd_config_update_free_global"}, + {(void**)&psnd_strerror, "snd_strerror"}, + {(void**)&psnd_pcm_hw_params_any, "snd_pcm_hw_params_any"}, + {(void**)&psnd_pcm_hw_params_set_access, "snd_pcm_hw_params_set_access"}, + {(void**)&psnd_pcm_hw_params_set_format, "snd_pcm_hw_params_set_format"}, + {(void**)&psnd_pcm_hw_params_set_channels, "snd_pcm_hw_params_set_channels"}, + {(void**)&psnd_pcm_hw_params_set_rate_near, "snd_pcm_hw_params_set_rate_near"}, + {(void**)&psnd_pcm_hw_params_set_period_size_near, "snd_pcm_hw_params_set_period_size_near"}, + {(void**)&psnd_pcm_hw_params, "snd_pcm_hw_params"}, + {(void**)&psnd_pcm_sw_params_current, "snd_pcm_sw_params_current"}, + {(void**)&psnd_pcm_sw_params_set_start_threshold, "snd_pcm_sw_params_set_start_threshold"}, + {(void**)&psnd_pcm_sw_params_set_stop_threshold, "snd_pcm_sw_params_set_stop_threshold"}, + {(void**)&psnd_pcm_sw_params, "snd_pcm_sw_params"}, + {(void**)&psnd_pcm_hw_params_get_buffer_size, "snd_pcm_hw_params_get_buffer_size"}, + {(void**)&psnd_pcm_avail_update, "snd_pcm_avail_update"}, + {(void**)&psnd_pcm_state, "snd_pcm_state"}, + {(void**)&psnd_pcm_start, "snd_pcm_start"}, + {(void**)&psnd_pcm_recover, "snd_pcm_recover"}, + {(void**)&psnd_pcm_set_params, "snd_pcm_set_params"}, + {(void**)&psnd_pcm_hw_params_sizeof, "snd_pcm_hw_params_sizeof"}, + {(void**)&psnd_pcm_sw_params_sizeof, "snd_pcm_sw_params_sizeof"}, + {(void**)&psnd_pcm_hw_params_set_buffer_size_near, "snd_pcm_hw_params_set_buffer_size_near"}, + + {(void**)&psnd_pcm_mmap_begin, "snd_pcm_mmap_begin"}, + {(void**)&psnd_pcm_mmap_commit, "snd_pcm_mmap_commit"}, + + {(void**)&psnd_pcm_writei, "snd_pcm_writei"}, + {(void**)&psnd_pcm_prepare, "snd_pcm_prepare"}, + + {(void**)&psnd_device_name_hint, "snd_device_name_hint"}, + {(void**)&psnd_device_name_get_hint, "snd_device_name_get_hint"}, + {(void**)&psnd_device_name_free_hint, "snd_device_name_free_hint"}, + {NULL,NULL} + }; + if (tried) return alsaworks; tried = true; @@ -211,80 +251,13 @@ static qboolean Alsa_InitAlsa(void) return false; // Try alternative names of libasound, sometimes it is not linked correctly. - alsasharedobject = dlopen("libasound.so.2", RTLD_LAZY|RTLD_LOCAL); + alsasharedobject = Sys_LoadLibrary("libasound.so.2", funcs); if (!alsasharedobject) - { - alsasharedobject = dlopen("libasound.so", RTLD_LAZY|RTLD_LOCAL); - if (!alsasharedobject) - { - return false; - } - } - - - psnd_pcm_open = dlsym(alsasharedobject, "snd_pcm_open"); - psnd_pcm_close = dlsym(alsasharedobject, "snd_pcm_close"); - psnd_config_update_free_global = dlsym(alsasharedobject, "snd_config_update_free_global"); - psnd_strerror = dlsym(alsasharedobject, "snd_strerror"); - psnd_pcm_hw_params_any = dlsym(alsasharedobject, "snd_pcm_hw_params_any"); - psnd_pcm_hw_params_set_access = dlsym(alsasharedobject, "snd_pcm_hw_params_set_access"); - psnd_pcm_hw_params_set_format = dlsym(alsasharedobject, "snd_pcm_hw_params_set_format"); - psnd_pcm_hw_params_set_channels = dlsym(alsasharedobject, "snd_pcm_hw_params_set_channels"); - psnd_pcm_hw_params_set_rate_near = dlsym(alsasharedobject, "snd_pcm_hw_params_set_rate_near"); - psnd_pcm_hw_params_set_period_size_near = dlsym(alsasharedobject, "snd_pcm_hw_params_set_period_size_near"); - psnd_pcm_hw_params = dlsym(alsasharedobject, "snd_pcm_hw_params"); - psnd_pcm_sw_params_current = dlsym(alsasharedobject, "snd_pcm_sw_params_current"); - psnd_pcm_sw_params_set_start_threshold = dlsym(alsasharedobject, "snd_pcm_sw_params_set_start_threshold"); - psnd_pcm_sw_params_set_stop_threshold = dlsym(alsasharedobject, "snd_pcm_sw_params_set_stop_threshold"); - psnd_pcm_sw_params = dlsym(alsasharedobject, "snd_pcm_sw_params"); - psnd_pcm_hw_params_get_buffer_size = dlsym(alsasharedobject, "snd_pcm_hw_params_get_buffer_size"); - psnd_pcm_avail_update = dlsym(alsasharedobject, "snd_pcm_avail_update"); - psnd_pcm_state = dlsym(alsasharedobject, "snd_pcm_state"); - psnd_pcm_start = dlsym(alsasharedobject, "snd_pcm_start"); - psnd_pcm_recover = dlsym(alsasharedobject, "snd_pcm_recover"); - psnd_pcm_set_params = dlsym(alsasharedobject, "snd_pcm_set_params"); - psnd_pcm_hw_params_sizeof = dlsym(alsasharedobject, "snd_pcm_hw_params_sizeof"); - psnd_pcm_sw_params_sizeof = dlsym(alsasharedobject, "snd_pcm_sw_params_sizeof"); - psnd_pcm_hw_params_set_buffer_size_near = dlsym(alsasharedobject, "snd_pcm_hw_params_set_buffer_size_near"); - - psnd_pcm_mmap_begin = dlsym(alsasharedobject, "snd_pcm_mmap_begin"); - psnd_pcm_mmap_commit = dlsym(alsasharedobject, "snd_pcm_mmap_commit"); - - psnd_pcm_writei = dlsym(alsasharedobject, "snd_pcm_writei"); - psnd_pcm_prepare = dlsym(alsasharedobject, "snd_pcm_prepare"); - - psnd_device_name_hint = dlsym(alsasharedobject, "snd_device_name_hint"); - psnd_device_name_get_hint = dlsym(alsasharedobject, "snd_device_name_get_hint"); - psnd_device_name_free_hint = dlsym(alsasharedobject, "snd_device_name_free_hint"); - - alsaworks = psnd_pcm_open - && psnd_pcm_close - && psnd_config_update_free_global - && psnd_strerror - && psnd_pcm_hw_params_any - && psnd_pcm_hw_params_set_access - && psnd_pcm_hw_params_set_format - && psnd_pcm_hw_params_set_channels - && psnd_pcm_hw_params_set_rate_near - && psnd_pcm_hw_params_set_period_size_near - && psnd_pcm_hw_params - && psnd_pcm_sw_params_current - && psnd_pcm_sw_params_set_start_threshold - && psnd_pcm_sw_params_set_stop_threshold - && psnd_pcm_sw_params - && psnd_pcm_hw_params_get_buffer_size - && psnd_pcm_avail_update - && psnd_pcm_state - && psnd_pcm_start - && psnd_pcm_hw_params_sizeof - && psnd_pcm_sw_params_sizeof - && psnd_pcm_hw_params_set_buffer_size_near - && psnd_pcm_mmap_begin - && psnd_pcm_mmap_commit - && psnd_pcm_writei && psnd_pcm_prepare - && psnd_device_name_hint && psnd_device_name_get_hint && psnd_device_name_free_hint - ; + alsasharedobject = Sys_LoadLibrary("libasound.so", funcs); + if (!alsasharedobject) + return false; + alsaworks = true; return alsaworks; } diff --git a/engine/client/snd_dma.c b/engine/client/snd_dma.c index c9ad2fb37..c2eba062a 100644 --- a/engine/client/snd_dma.c +++ b/engine/client/snd_dma.c @@ -3143,12 +3143,13 @@ float S_GetChannelLevel(int entnum, int entchannel) if (sc->channel[i].entnum == entnum && sc->channel[i].entchannel == entchannel && sc->channel[i].sfx) { ssamplepos_t spos = sc->GetChannelPos?sc->GetChannelPos(sc, &sc->channel[i]):(sc->channel[i].pos>>PITCHSHIFT); - if (sc->channel[i].sfx->decoder.decodedata)scache = sc->channel[i].sfx->decoder.decodedata(sc->channel[i].sfx, &scachebuf, spos, 1); + if (sc->channel[i].sfx->decoder.decodedata) + scache = sc->channel[i].sfx->decoder.decodedata(sc->channel[i].sfx, &scachebuf, spos, 1); else scache = NULL; - if (!scache) scache = sc->channel[i].sfx->decoder.buf; + if (scache && spos >= scache->soundoffset && spos < scache->soundoffset+scache->length) { spos -= scache->soundoffset; diff --git a/engine/client/snd_pulse.c b/engine/client/snd_pulse.c index b4e3da5e6..d9b5efebd 100644 --- a/engine/client/snd_pulse.c +++ b/engine/client/snd_pulse.c @@ -1,5 +1,5 @@ #include "quakedef.h" -#ifdef HAVE_MIXER +#if defined(HAVE_MIXER) && defined(MULTITHREAD) #if 0 #include diff --git a/engine/client/snd_sdl.c b/engine/client/snd_sdl.c index 13fcc2b04..fa7b4c52b 100644 --- a/engine/client/snd_sdl.c +++ b/engine/client/snd_sdl.c @@ -128,13 +128,13 @@ static qboolean SSDL_InitAudio(void) #endif if (!inited) - if(SDL_InitSubSystem(SDL_INIT_AUDIO | SDL_INIT_NOPARACHUTE)) - { + { + if(0==SDL_InitSubSystem(SDL_INIT_AUDIO | SDL_INIT_NOPARACHUTE)) + inited = true; + else Con_Printf("Couldn't initialize SDL audio subsystem (%s)\n", SDL_GetError()); - return false; - } - inited = true; - return true; + } + return inited; } #else #define SDL_VERSION_ATLEAST(x,y,z) 0 diff --git a/engine/client/sys_linux.c b/engine/client/sys_linux.c index 20d7e29f4..c9faa7b0e 100644 --- a/engine/client/sys_linux.c +++ b/engine/client/sys_linux.c @@ -99,7 +99,7 @@ qboolean isDedicated; #if 1 static int ansiremap[8] = {0, 4, 2, 6, 1, 5, 3, 7}; -static void ApplyColour(unsigned int chrflags) +static void ApplyColour(FILE *out, unsigned int chrflags) { static int oldflags = CON_WHITEMASK; int bg, fg; @@ -108,10 +108,10 @@ static void ApplyColour(unsigned int chrflags) return; oldflags = chrflags; - printf("\e[0;"); // reset + fprintf(out, "\e[0;"); // reset if (chrflags & CON_BLINKTEXT) - printf("5;"); // set blink + fprintf(out, "5;"); // set blink bg = (chrflags & CON_BGMASK) >> CON_BGSHIFT; fg = (chrflags & CON_FGMASK) >> CON_FGSHIFT; @@ -124,12 +124,12 @@ static void ApplyColour(unsigned int chrflags) { if (fg & 0x8) // intensive bit set for foreground { - printf("1;"); // set bold/intensity ansi flag + fprintf(out, "1;"); // set bold/intensity ansi flag fg &= 0x7; // strip intensive bit } // set foreground and background colors - printf("3%i;4%im", ansiremap[fg], ansiremap[bg]); + fprintf(out, "3%i;4%im", ansiremap[fg], ansiremap[bg]); } else { @@ -137,22 +137,22 @@ static void ApplyColour(unsigned int chrflags) { //to get around wierd defaults (like a white background) we have these special hacks for colours 0 and 7 case COLOR_BLACK: - printf("7m"); // set inverse + fprintf(out, "7m"); // set inverse break; case COLOR_GREY: - printf("1;30m"); // treat as dark grey + fprintf(out, "1;30m"); // treat as dark grey break; case COLOR_WHITE: - printf("m"); // set nothing else + fprintf(out, "m"); // set nothing else break; default: if (fg & 0x8) // intensive bit set for foreground { - printf("1;"); // set bold/intensity ansi flag + fprintf(out, "1;"); // set bold/intensity ansi flag fg &= 0x7; // strip intensive bit } - printf("3%im", ansiremap[fg]); // set foreground + fprintf(out, "3%im", ansiremap[fg]); // set foreground break; } } @@ -167,9 +167,16 @@ void Sys_Printf (char *fmt, ...) conchar_t *c, *e; wchar_t w; unsigned int codeflags, codepoint; + FILE *out = stdout; if (nostdout) + { +#ifdef _DEBUG + out = stderr; +#else return; +#endif + } va_start (argptr,fmt); vsnprintf (text,sizeof(text)-1, fmt,argptr); @@ -188,26 +195,26 @@ void Sys_Printf (char *fmt, ...) if ((codeflags&CON_RICHFORECOLOUR) || (codepoint == '\n' && (codeflags&CON_NONCLEARBG))) codeflags = CON_WHITEMASK; //make sure we don't get annoying backgrounds on other lines. - ApplyColour(codeflags); + ApplyColour(out, codeflags); w = codepoint; if (w >= 0xe000 && w < 0xe100) { /*not all quake chars are ascii compatible, so map those control chars to safe ones so we don't mess up anyone's xterm*/ if ((w & 0x7f) > 0x20) - putc(w&0x7f, stdout); + putc(w&0x7f, out); else if (w & 0x80) { static char tab[32] = "---#@.@@@@ # >.." "[]0123456789.---"; - putc(tab[w&31], stdout); + putc(tab[w&31], out); } else { static char tab[32] = ".####.#### # >.." "[]0123456789.---"; - putc(tab[w&31], stdout); + putc(tab[w&31], out); } } else if (w < ' ' && w != '\t' && w != '\r' && w != '\n') - putc('?', stdout); //don't let anyone print escape codes or other things that could crash an xterm. + putc('?', out); //don't let anyone print escape codes or other things that could crash an xterm. else { /*putwc doesn't like me. force it in utf8*/ @@ -215,20 +222,20 @@ void Sys_Printf (char *fmt, ...) { if (w > 0x800) { - putc(0xe0 | ((w>>12)&0x0f), stdout); - putc(0x80 | ((w>>6)&0x3f), stdout); + putc(0xe0 | ((w>>12)&0x0f), out); + putc(0x80 | ((w>>6)&0x3f), out); } else - putc(0xc0 | ((w>>6)&0x1f), stdout); - putc(0x80 | (w&0x3f), stdout); + putc(0xc0 | ((w>>6)&0x1f), out); + putc(0x80 | (w&0x3f), out); } else - putc(w, stdout); + putc(w, out); } } - ApplyColour(CON_WHITEMASK); - fflush(stdout); + ApplyColour(out, CON_WHITEMASK); + fflush(out); } #else void Sys_Printf (char *fmt, ...) @@ -736,9 +743,9 @@ dllhandle_t *Sys_LoadLibrary(const char *name, dllfunction_t *funcs) lib = NULL; if (!lib) - lib = dlopen (name, RTLD_LAZY); + lib = dlopen (name, RTLD_LOCAL|RTLD_LAZY); if (!lib && !strstr(name, ".so")) - lib = dlopen (va("%s.so", name), RTLD_LAZY); + lib = dlopen (va("%s.so", name), RTLD_LOCAL|RTLD_LAZY); if (!lib) { Con_DLPrintf(2,"%s\n", dlerror()); @@ -884,6 +891,17 @@ char *Sys_ConsoleInput(void) if (noconinput) return NULL; +#if defined(__linux__) && defined(_DEBUG) + { + int fl = fcntl (STDIN_FILENO, F_GETFL, 0); + if (!(fl & FNDELAY)) + { + fcntl(STDIN_FILENO, F_SETFL, fl | FNDELAY); + Sys_Printf(CON_WARNING "stdin flags became blocking - gdb bug?\n"); + } + } +#endif + // if (!qrenderer) { if (!fgets(text, sizeof(text), stdin)) @@ -1001,7 +1019,7 @@ int main (int c, const char **v) noconinput = COM_CheckParm("-noconinput"); #ifndef __DJGPP__ if (!noconinput) - fcntl(0, F_SETFL, fcntl (0, F_GETFL, 0) | FNDELAY); + fcntl(STDIN_FILENO, F_SETFL, fcntl (0, F_GETFL, 0) | FNDELAY); #endif #ifndef CLIENTONLY diff --git a/engine/common/com_mesh.c b/engine/common/com_mesh.c index 9ae7c4ef2..aa7d2657d 100644 --- a/engine/common/com_mesh.c +++ b/engine/common/com_mesh.c @@ -4432,7 +4432,377 @@ static qboolean QDECL Mod_LoadQ2Model (model_t *mod, void *buffer, size_t fsize) #endif +#ifdef MODELFMT_MDX +//////////////////////////////////////////////////////////////////////////////////////////////////////////////// +//Kingpin model loading +//basically md2, but with toggleable subobjects and object bounding boxes (fixme: use those for hitmesh instead of the mesh itself) + +typedef struct +{ + float scale[3]; // multiply qbyte verts by this + float translate[3]; // then add this + char name[16]; // frame name from grabbing + dtrivertx_t verts[1]; // variable sized +} dmdxframe_t; + +typedef struct +{ + int cmd; + int obj; + struct dmdxcommandvert_s + { + float s, t; + int origvert; + } vert[1]; +} dmdxcommand_t; + +typedef struct +{ + int magic; + int version; + int skinWidth; + int skinHeight; + int frameSize; + int numSkins; + int numVertices; + int numTriangles_Unusable; + int numGlCommands; + int numFrames; + int numSfxDefines_Unsupported; + int numSfxEntries_Unsupported; + int numSubObjects; + int offsetSkins; + int offsetTriangles_Unusable; + int offsetFrames; + int offsetGlCommands; + int offsetVertexInfo_Whatever; + int offsetSfxDefines_Unsupported; + int offsetSfxEntries_Unsupported; + int offsetBBoxFrames_HitmeshInstead; + int offsetMaybeST_Bugged; + int offsetEnd; +} dmdxheader_t; + +#define MDX_IDENT ('I'<<0)+('D'<<8)+('P'<<16)+('X'<<24) +#define MDX_VERSION 4 + +#define Q2NUMVERTEXNORMALS 162 +extern vec3_t bytedirs[Q2NUMVERTEXNORMALS]; + +#ifndef SERVERONLY +static void MDX_LoadSkins(galiasinfo_t *galias, model_t *mod, dmdxheader_t *pinmodel, char *skins) +{ + int i; + skinframe_t *frames; + galiasskin_t *outskin = galias->ofsskins; + + for (i = 0; i < LittleLong(pinmodel->numSkins); i++, outskin++) + { + frames = ZG_Malloc(&mod->memgroup, sizeof(*frames)); + outskin->frame = frames; + outskin->numframes=1; + + COM_CleanUpPath(skins); //blooming tanks. + Q_strncpyz(frames->shadername, skins, sizeof(frames->shadername)); + + outskin->skinwidth = 0; + outskin->skinheight = 0; + outskin->skinspeed = 0; + + skins += MD2MAX_SKINNAME; + } + galias->numskins = LittleLong(pinmodel->numSkins); +} +#endif + +#define MDX_MAX_TRIANGLES 4096 +#define MDX_MAX_VERTS MDX_MAX_TRIANGLES*3 +static int MDX_MatchVert(struct dmdxcommandvert_s *list, int *count, struct dmdxcommandvert_s *newvert) +{ + int i; + for (i = 0; i < *count; i++) + { + if (list[i].origvert == newvert->origvert && + list[i].s == newvert->s && + list[i].t == newvert->t) + return i; //its a dupe! + } + if (i == MDX_MAX_VERTS) + return 0; + list[i] = *newvert; + *count+=1; + return i; +} + +static qboolean QDECL Mod_LoadKingpinModel (model_t *mod, void *buffer, size_t fsize) +{ +#ifndef SERVERONLY + vec2_t *st_array; + vec3_t *normals; +#endif + dmdxheader_t *pinmodel; + + int version; + int i, j, subobj; + index_t *indexes; + + vec3_t min; + vec3_t max; + + galiaspose_t *pose; + galiasanimation_t *poutframe; + dmdxframe_t *pinframe; + int framesize; + vecV_t *verts; + dmdxcommand_t *pincmd, *pincmdend; + + struct dmdxcommandvert_s tmpvert[MDX_MAX_VERTS]; + int numverts; + struct + { + int newidx[3]; + } tri[MDX_MAX_TRIANGLES]; + int numtri; + + int size; + galiasinfo_t *galias, *root; + + mod->engineflags |= MDLF_NEEDOVERBRIGHT; + + pinmodel = (dmdxheader_t *)buffer; + + if (fsize < sizeof(*pinmodel)) + { + Con_Printf (CON_ERROR "%s is truncated\n", mod->name); + return false; + } + version = LittleLong (pinmodel->version); + if (version != MDX_VERSION) + { + Con_Printf (CON_ERROR "%s has wrong version number (%i should be %i)\n", + mod->name, version, MDX_VERSION); + return false; + } + if (LittleLong(pinmodel->offsetEnd) != fsize) + { + Con_Printf (CON_ERROR "%s is truncated\n", mod->name); + return false; + } + + if (LittleLong(pinmodel->numFrames) < 1 || + LittleLong(pinmodel->numSkins) < 0 || + LittleLong(pinmodel->numTriangles_Unusable) < 1 || + LittleLong(pinmodel->numVertices) < 3 || + LittleLong(pinmodel->skinHeight) < 1 || + LittleLong(pinmodel->skinWidth) < 1 || + LittleLong(pinmodel->numSubObjects) < 1) + { + Con_Printf(CON_ERROR "Model %s has an invalid quantity\n", mod->name); + return false; + } + + mod->flags = 0; + + mod->numframes = LittleLong(pinmodel->numFrames); + + size = sizeof(galiasinfo_t)*pinmodel->numSubObjects + + LittleLong(pinmodel->numFrames)*sizeof(galiasanimation_t)*pinmodel->numSubObjects +#ifndef SERVERONLY + + LittleLong(pinmodel->numSkins)*sizeof(galiasskin_t) +#endif + ; + + root = galias = ZG_Malloc(&mod->memgroup, size); + +#ifndef SERVERONLY +//skins + galias->ofsskins = (galiasskin_t*)((galiasanimation_t*)(galias+pinmodel->numSubObjects) + LittleLong(pinmodel->numFrames)*pinmodel->numSubObjects); + MDX_LoadSkins(galias, mod, pinmodel, ((char *)pinmodel+LittleLong(pinmodel->offsetSkins))); +#else + galias->numskins = LittleLong(pinmodel->numSkins); +#endif + + ClearBounds (mod->mins, mod->maxs); + for (subobj = 0; subobj < pinmodel->numSubObjects; subobj++) + { + galias = &root[subobj]; + Mod_DefaultMesh(galias, mod->name, subobj); + galias->ofsanimations = (galiasanimation_t*)(root+pinmodel->numSubObjects) + subobj*pinmodel->numFrames; + galias->ofsskins = root->ofsskins; + galias->numskins = root->numskins; + galias->shares_verts = subobj; + if (subobj > 0) + root[subobj-1].nextsurf = galias; + + //process the strips+fans, and split the verts into the appropriate submesh + pincmd = (dmdxcommand_t *)((char *)pinmodel + LittleLong(pinmodel->offsetGlCommands)); + pincmdend = (dmdxcommand_t *)((char *)pinmodel + LittleLong(pinmodel->offsetGlCommands) + LittleLong(pinmodel->numGlCommands)*4); + numverts = 0; + numtri = 0; + while (pincmd < pincmdend) + { + int n = LittleLong(pincmd->cmd); + if (!n) + break; //no more commands + if (n < 0) + { //fan club + n = -n; + if (n > 2 && LittleLong(pincmd->obj) == subobj) + { + int first = MDX_MatchVert(tmpvert, &numverts, &pincmd->vert[0]); + int prev = MDX_MatchVert(tmpvert, &numverts, &pincmd->vert[1]); + for (i = 2; i < n && numtri < countof(tri); i++) + { + tri[numtri].newidx[0] = first; + tri[numtri].newidx[1] = prev; + tri[numtri].newidx[2] = prev = MDX_MatchVert(tmpvert, &numverts, &pincmd->vert[i]); + numtri++; + } + } + } + else + { //stripper + if (n > 2 && LittleLong(pincmd->obj) == subobj) + { + int first = MDX_MatchVert(tmpvert, &numverts, &pincmd->vert[0]); + int prev = MDX_MatchVert(tmpvert, &numverts, &pincmd->vert[1]); + for (i = 2; i < n && numtri < countof(tri); i++) + { + tri[numtri].newidx[2] = MDX_MatchVert(tmpvert, &numverts, &pincmd->vert[i]); + if (i&1) + { + tri[numtri].newidx[0] = prev; + tri[numtri].newidx[1] = first; + } + else + { + tri[numtri].newidx[0] = first; + tri[numtri].newidx[1] = prev; + } + first = prev; + prev = tri[numtri].newidx[2]; + + if (tri[numtri].newidx[0] == tri[numtri].newidx[1] || + tri[numtri].newidx[0] == tri[numtri].newidx[2] || + tri[numtri].newidx[1] == tri[numtri].newidx[2]) + continue; //degenerate... I doubt we'll see any though. + numtri++; + } + } + } + pincmd = (dmdxcommand_t*)&pincmd->vert[n]; + } + for (i = 0; i < numverts; i++) + { //might as well byteswap that stuff now... + tmpvert[i].origvert = LittleLong(tmpvert[i].origvert); + tmpvert[i].s = LittleFloat(tmpvert[i].s); + tmpvert[i].t = LittleFloat(tmpvert[i].t); + } + + galias->numverts = numverts; + galias->numindexes = numtri*3; + indexes = ZG_Malloc(&mod->memgroup, galias->numindexes*sizeof(*indexes)); + galias->ofs_indexes = indexes; + + for (i = 0; i < numtri; i++, indexes+=3) + { + indexes[0] = tri[i].newidx[0]; + indexes[1] = tri[i].newidx[1]; + indexes[2] = tri[i].newidx[2]; + } + + // s and t vertices +#ifndef SERVERONLY + st_array = ZG_Malloc(&mod->memgroup, sizeof(*st_array)*(numverts)); + galias->ofs_st_array = st_array; + + for (j=0 ; jofsanimations; + framesize = LittleLong (pinmodel->frameSize); + + size = sizeof(galiaspose_t) + sizeof(vecV_t)*numverts; +#ifndef SERVERONLY + size += 3*sizeof(vec3_t)*numverts; +#endif + size *= pinmodel->numFrames; + pose = (galiaspose_t *)ZG_Malloc(&mod->memgroup, size); + verts = (vecV_t*)(pose+pinmodel->numFrames); +#ifndef SERVERONLY + normals = (vec3_t*)(verts+pinmodel->numFrames*numverts); +#endif + + for (i=0 ; inumFrames) ; i++) + { + poutframe->poseofs = pose; + poutframe->numposes = 1; + galias->numanimations++; + +#ifndef SERVERONLY + pose->ofsnormals = normals; + pose->ofssvector = &normals[galias->numverts]; + pose->ofstvector = &normals[galias->numverts*2]; +#endif + + pinframe = ( dmdxframe_t * )( ( qbyte * )pinmodel + LittleLong (pinmodel->offsetFrames) + i * framesize ); + Q_strncpyz(poutframe->name, pinframe->name, sizeof(poutframe->name)); + + for (j=0 ; j<3 ; j++) + { + pose->scale[j] = LittleFloat (pinframe->scale[j]); + pose->scale_origin[j] = LittleFloat (pinframe->translate[j]); + } + + pose->ofsverts = verts; + for (j=0 ; jscale_origin[0]+pose->scale[0]*pinframe->verts[tmpvert[j].origvert].v[0]; + verts[j][1] = pose->scale_origin[1]+pose->scale[1]*pinframe->verts[tmpvert[j].origvert].v[1]; + verts[j][2] = pose->scale_origin[2]+pose->scale[2]*pinframe->verts[tmpvert[j].origvert].v[2]; +#ifndef SERVERONLY + VectorCopy(bytedirs[pinframe->verts[tmpvert[j].origvert].lightnormalindex], normals[j]); +#endif + } + + VectorCopy ( pose->scale_origin, min ); + VectorMA ( pose->scale_origin, 255, pose->scale, max ); + + AddPointToBounds ( min, mod->mins, mod->maxs ); + AddPointToBounds ( max, mod->mins, mod->maxs ); + + poutframe++; + pose++; + verts += numverts; +#ifndef SERVERONLY + normals += numverts*3; +#endif + } + + Mod_CompileTriangleNeighbours(mod, galias); + Mod_BuildTextureVectors(galias); + } + + mod->radius = RadiusFromBounds(mod->mins, mod->maxs); + Mod_ClampModelSize(mod); + Mod_ParseModelEvents(mod, root->ofsanimations, root->numanimations); + + mod->meshinfo = root; + mod->numframes = root->numanimations; + mod->type = mod_alias; + + mod->funcs.NativeTrace = Mod_Trace; + + return true; +} +#endif @@ -8807,6 +9177,9 @@ void Alias_Register(void) #ifdef MD2MODELS Mod_RegisterModelFormatMagic(NULL, "Quake2 Model (md2)", MD2IDALIASHEADER, Mod_LoadQ2Model); #endif +#ifdef MODELFMT_MDX + Mod_RegisterModelFormatMagic(NULL, "Kingpin Model (mdx)", MDX_IDENT, Mod_LoadKingpinModel); +#endif #ifdef MD3MODELS Mod_RegisterModelFormatMagic(NULL, "Quake3 Model (md3)", MD3_IDENT, Mod_LoadQ3Model); #endif diff --git a/engine/common/common.c b/engine/common/common.c index 111b2f0b0..b938535ef 100644 --- a/engine/common/common.c +++ b/engine/common/common.c @@ -5228,7 +5228,7 @@ static void COM_ErrorMe_f(void) #ifdef LOADERTHREAD static void QDECL COM_WorkerCount_Change(cvar_t *var, char *oldvalue); cvar_t worker_flush = CVARD("worker_flush", "1", "If set, process the entire load queue, loading stuff faster but at the risk of stalling the main thread."); -static cvar_t worker_count = CVARFCD("worker_count", "0", CVAR_NOTFROMSERVER, COM_WorkerCount_Change, "Specifies the number of worker threads to utilise."); +static cvar_t worker_count = CVARFCD("worker_count", "", CVAR_NOTFROMSERVER, COM_WorkerCount_Change, "Specifies the number of worker threads to utilise."); static cvar_t worker_sleeptime = CVARFD("worker_sleeptime", "0", CVAR_NOTFROMSERVER, "Causes workers to sleep for a period of time after each job."); #define WORKERTHREADS 16 //max @@ -5475,7 +5475,9 @@ static int COM_WorkerThread(void *arg) thread->request = WR_NONE; thread->ackseq = com_workeracksequence; Sys_UnlockConditional(com_workercondition[group]); + Sys_LockConditional(com_workercondition[WG_MAIN]); Sys_ConditionBroadcast(com_workercondition[WG_MAIN]); //try to wake up whoever wanted us to ack them + Sys_UnlockConditional(com_workercondition[WG_MAIN]); Sys_LockConditional(com_workercondition[group]); continue; } diff --git a/engine/common/config_fteqw.h b/engine/common/config_fteqw.h index b6d9e6b43..b285f646a 100644 --- a/engine/common/config_fteqw.h +++ b/engine/common/config_fteqw.h @@ -83,11 +83,13 @@ #define PSKMODELS //unreal's interchange format. Undesirable in terms of load times. #define HALFLIFEMODELS //horrible format that doesn't interact well with the rest of FTE's code. Unusable tools (due to license reasons). #define INTERQUAKEMODELS //Preferred model format, at least from an idealism perspective. +#define MODELFMT_MDX //kingpin's format (for hitboxes+geomsets). #define RAGDOLL //ragdoll support. requires RBE support (via a plugin...). //Image formats #define IMAGEFMT_KTX //Khronos TeXture. common on gles3 devices for etc2 compression #define IMAGEFMT_PKM //file format generally written by etcpack or android's etc1tool. doesn't support mips. +#define IMAGEFMT_ASTC //lame simple header around a single astc image. not needed for astc in ktx files etc. its better to use ktx files. #define IMAGEFMT_PBM //pbm/ppm/pgm/pfm family formats. #define IMAGEFMT_PSD //baselayer only. #define IMAGEFMT_HDR //an RGBE format. @@ -104,6 +106,7 @@ #define DECOMPRESS_S3TC //allows bc1-3 to work even when drivers don't support it. This is probably only an issue on mobile chips. WARNING: not entirely sure if all patents expired yet... #define DECOMPRESS_RGTC //bc4+bc5 #define DECOMPRESS_BPTC //bc6+bc7 +#define DECOMPRESS_ASTC //ASTC, for drivers that don't support it properly. // Game/Gamecode Support #define CSQC_DAT diff --git a/engine/common/console.h b/engine/common/console.h index ac3241f2d..734209365 100644 --- a/engine/common/console.h +++ b/engine/common/console.h @@ -170,8 +170,9 @@ typedef struct console_s conline_t *oldest; conline_t *current; // line where next message will be printed int x; // offset in current line for next print - int cr; + int cr; // last char printed was a carrage return so the next char printed will wipe the line. conline_t *display; // bottom of console displays this line + float displayscroll; // to try to handle smoother scrolling. int displayoffset; // horizontal offset int vislines; // pixel lines int linesprinted; // for notify times @@ -194,9 +195,9 @@ typedef struct console_s conline_t *footerline; //temp text at the bottom of the console conline_t *selstartline, *selendline; unsigned int selstartoffset, selendoffset; - int mousedown[2]; //x,y position that the current buttons were clicked. + float mousedown[2]; //x,y position that the current buttons were clicked. unsigned int buttonsdown; - int mousecursor[2]; //x,y + float mousecursor[2]; //x,y float mousedowntime; //time mouse1 last went down, to detect double-clicks struct console_s *next; diff --git a/engine/common/fs.c b/engine/common/fs.c index abc405d9e..43c85c625 100644 --- a/engine/common/fs.c +++ b/engine/common/fs.c @@ -810,6 +810,7 @@ static int QDECL COM_Dir_List(const char *name, qofs_t size, time_t mtime, void } else if (!Q_strcasecmp(link, "bsp") || !Q_strcasecmp(link, "spr") || !Q_strcasecmp(link, "mdl") || !Q_strcasecmp(link, "md3") || !Q_strcasecmp(link, "iqm") || !Q_strcasecmp(link, "vvm") || !Q_strcasecmp(link, "psk") || !Q_strcasecmp(link, "dpm") || !Q_strcasecmp(link, "zym") || !Q_strcasecmp(link, "md5mesh") || + !Q_strcasecmp(link, "mdx") || !Q_strcasecmp(link, "md2") || !Q_strcasecmp(link, "md5anim") || !Q_strcasecmp(link, "gltf") || !Q_strcasecmp(link, "glb") || !Q_strcasecmp(link, "ase") || !Q_strcasecmp(link, "lwo")) Q_snprintfz(link, sizeof(link), "\\tip\\Open in Model Viewer\\modelviewer\\%s", name); else if (!Q_strcasecmp(link, "qc") || !Q_strcasecmp(link, "src") || !Q_strcasecmp(link, "qh") || !Q_strcasecmp(link, "h") || !Q_strcasecmp(link, "c") @@ -2417,10 +2418,8 @@ typedef struct { const char *puredesc; unsigned int inheritflags; } wildpaks_t; - -static int QDECL FS_AddWildDataFiles (const char *descriptor, qofs_t size, time_t mtime, void *vparam, searchpathfuncs_t *funcs) +static void FS_AddSingleDataFile (const char *descriptor, wildpaks_t *param, searchpathfuncs_t *funcs) { - wildpaks_t *param = vparam; vfsfile_t *vfs; searchpath_t *search; searchpathfuncs_t *newpak; @@ -2434,7 +2433,7 @@ static int QDECL FS_AddWildDataFiles (const char *descriptor, qofs_t size, time_ for (search = com_searchpaths; search; search = search->next) { if (!Q_strcasecmp(search->logicalpath, pakfile)) //assumption: first member of structure is a char array - return true; //already loaded (base paths?) + return; //already loaded (base paths?) } newpak = FS_GetOldPath(param->oldpaths, pakfile, &keptflags); @@ -2448,16 +2447,16 @@ static int QDECL FS_AddWildDataFiles (const char *descriptor, qofs_t size, time_ { fs_finds++; if (!funcs->FindFile(funcs, &loc, descriptor, NULL)) - return true; //not found.. + return; //not found.. vfs = funcs->OpenVFS(funcs, &loc, "rb"); if (!vfs) - return true; + return; } newpak = param->OpenNew (vfs, funcs, descriptor, pakfile, ""); if (!newpak) { VFS_CLOSE(vfs); - return true; + return; } } @@ -2467,8 +2466,78 @@ static int QDECL FS_AddWildDataFiles (const char *descriptor, qofs_t size, time_ else Q_strncpyz(purefile, descriptor, sizeof(purefile)); FS_AddPathHandle(param->oldpaths, purefile, pakfile, newpak, "", ((!Q_strncasecmp(descriptor, "pak", 3))?SPF_COPYPROTECTED:0)|keptflags|param->inheritflags, (unsigned int)-1); +} +typedef struct +{ + //name table, to avoid too many reallocs + char *names; + size_t numnames; + size_t maxnames; - return true; + //file table, again to avoid excess reallocs + struct wilddatafile_s + { + size_t nameofs; + size_t size; + time_t mtime; + searchpathfuncs_t *source; + } *files; + size_t numfiles; + size_t maxfiles; +} filelist_t; +static int QDECL FS_FindWildDataFiles (const char *descriptor, qofs_t size, time_t mtime, void *vparam, searchpathfuncs_t *funcs) +{ + filelist_t *list = vparam; + size_t name = list->numnames; + size_t file = list->numfiles; + + size_t dlen = strlen(descriptor); + + if (list->numnames + dlen+1 > list->maxnames) + Z_ReallocElements((void**)&list->names, &list->maxnames, list->numnames+dlen+1+8192, sizeof(*list->names)); + strcpy(list->names + name, descriptor); + list->numnames += dlen+1; + + if (list->numfiles + 1 > list->maxfiles) + Z_ReallocElements((void**)&list->files, &list->maxfiles, list->numfiles+1+128, sizeof(*list->files)); + list->files[file].nameofs = name; + list->files[file].size = size; + list->files[file].mtime = mtime; + list->files[file].source = funcs; + list->numfiles += 1; + + return true; //keep looking for more +} +static const char *qsortsucks; +static int QDECL FS_SortWildDataFiles(const void *va, const void *vb) +{ + const struct wilddatafile_s *a=va, *b=vb; + const char *na=qsortsucks+a->nameofs, *nb=qsortsucks+b->nameofs; + + //sort by modification time... + if (a->mtime != b->mtime && a->mtime && b->mtime) + return a->mtime > b->mtime; + + //then fall back and sort by name + return strcasecmp(na, nb); +} +static void FS_LoadWildDataFiles (filelist_t *list, wildpaks_t *wp) +{ + size_t f; + //sort them + qsortsucks = list->names; + qsort(list->files, list->numfiles, sizeof(*list->files), FS_SortWildDataFiles); + qsortsucks = NULL; + + for (f = 0; f < list->numfiles; f++) + FS_AddSingleDataFile(list->names+list->files[f].nameofs, wp, list->files[f].source); + list->numfiles = list->numnames = 0; + + Z_Free(list->files); + list->files = NULL; + Z_Free(list->names); + list->names = NULL; + list->maxfiles = list->maxnames = 0; } static searchpathfuncs_t *FS_OpenPackByExtension(vfsfile_t *f, searchpathfuncs_t *parent, const char *filename, const char *pakname) @@ -2645,6 +2714,7 @@ static void FS_AddDataFiles(searchpath_t **oldpaths, const char *purepath, const vfsfile_t *vfs; flocation_t loc; wildpaks_t wp; + filelist_t list = {0}; Q_strncpyz(logicalpaths, logicalpath, sizeof(logicalpaths)); FS_CleanDir(logicalpaths, sizeof(logicalpaths)); @@ -2680,7 +2750,7 @@ static void FS_AddDataFiles(searchpath_t **oldpaths, const char *purepath, const if (loadstuff & (1<handle); + FS_AddSingleDataFile(filename, &wp, search->handle); } break; } @@ -2754,7 +2824,8 @@ static void FS_AddDataFiles(searchpath_t **oldpaths, const char *purepath, const wp.OpenNew = searchpathformats[j].OpenNew; Q_snprintfz (pakfile, sizeof(pakfile), "*.%s", extension); - search->handle->EnumerateFiles(search->handle, pakfile, FS_AddWildDataFiles, &wp); + search->handle->EnumerateFiles(search->handle, pakfile, FS_FindWildDataFiles, &list); + FS_LoadWildDataFiles(&list, &wp); } } diff --git a/engine/common/net_wins.c b/engine/common/net_wins.c index 0274fc63a..a4b7e5123 100644 --- a/engine/common/net_wins.c +++ b/engine/common/net_wins.c @@ -2194,6 +2194,8 @@ neterr_t NET_SendLoopPacket (int sock, int length, const void *data, netadr_t *t { int i; loopback_t *loop; + if (!length && !data) //NET_EnsureRoute tests. + return NETERR_SENT; sock &= 1; diff --git a/engine/common/sys_linux_threads.c b/engine/common/sys_linux_threads.c index 1697fa86e..d080a5015 100644 --- a/engine/common/sys_linux_threads.c +++ b/engine/common/sys_linux_threads.c @@ -275,9 +275,6 @@ void Sys_Sleep (double seconds) #include #include #include -#define STDIN 0 -#define STDOUT 1 -#define STDERR 2 typedef struct slaveserver_s { @@ -386,10 +383,10 @@ pubsubserver_t *Sys_ForkServer(void) if (!pid) { //this is the child - dup2(toslave[0], STDIN); + dup2(toslave[0], STDIN_FILENO); close(toslave[1]); close(toslave[0]); - dup2(tomaster[1], STDOUT); + dup2(tomaster[1], STDOUT_FILENO); isClusterSlave = true; @@ -459,9 +456,9 @@ pubsubserver_t *Sys_ForkServer(void) posix_spawn_file_actions_addclose(&action, toslave[1]); posix_spawn_file_actions_addclose(&action, tomaster[0]); - posix_spawn_file_actions_adddup2(&action, toslave[0], STDIN); - posix_spawn_file_actions_adddup2(&action, tomaster[1], STDOUT); -// posix_spawn_file_actions_adddup2(&action, tomaster[1], STDERR); + posix_spawn_file_actions_adddup2(&action, toslave[0], STDIN_FILENO); + posix_spawn_file_actions_adddup2(&action, tomaster[1], STDOUT_FILENO); +// posix_spawn_file_actions_adddup2(&action, tomaster[1], STDERR_FILENO); posix_spawn_file_actions_addclose(&action, toslave[0]); posix_spawn_file_actions_addclose(&action, tomaster[1]); @@ -481,7 +478,7 @@ pubsubserver_t *Sys_ForkServer(void) void Sys_InstructMaster(sizebuf_t *cmd) { - write(STDOUT, cmd->data, cmd->cursize); + write(STDOUT_FILENO, cmd->data, cmd->cursize); //FIXME: handle partial writes. } @@ -490,6 +487,16 @@ void SSV_CheckFromMaster(void) { static char inbuffer[1024]; static int inbufsize; + +#if defined(__linux__) && defined(_DEBUG) + int fl = fcntl (STDIN_FILENO, F_GETFL, 0); + if (!(fl & FNDELAY)) + { + fcntl(STDIN_FILENO, F_SETFL, fl | FNDELAY); + Sys_Printf(CON_WARNING "stdin flags became blocking - gdb bug?\n"); + } +#endif + for(;;) { if(inbufsize >= 2) @@ -517,7 +524,7 @@ void SSV_CheckFromMaster(void) } { - ssize_t avail = read(STDIN, inbuffer+inbufsize, sizeof(inbuffer)-inbufsize); + ssize_t avail = read(STDIN_FILENO, inbuffer+inbufsize, sizeof(inbuffer)-inbufsize); if (!avail) { //eof SV_FinalMessage("Cluster shut down\n"); diff --git a/engine/gl/gl_alias.c b/engine/gl/gl_alias.c index 44cc14e3c..a1b91dce7 100644 --- a/engine/gl/gl_alias.c +++ b/engine/gl/gl_alias.c @@ -1770,6 +1770,8 @@ void R_GAlias_GenerateBatches(entity_t *e, batch_t **batches) for(surfnum=0; inf; inf=inf->nextsurf, surfnum++) { + if (!inf->numindexes) + continue; if (lod < inf->mindist || (inf->maxdist && lod >= inf->maxdist)) continue; diff --git a/engine/gl/gl_draw.c b/engine/gl/gl_draw.c index 2b37979d9..9ba2ff499 100644 --- a/engine/gl/gl_draw.c +++ b/engine/gl/gl_draw.c @@ -35,6 +35,8 @@ extern cvar_t gl_picmip2d; extern cvar_t gl_compress; extern cvar_t gl_smoothcrosshair; extern cvar_t gl_texturemode, gl_texture_anisotropic_filtering; +cvar_t gl_blacklist_texture_compression = CVARFD("gl_blacklist_texture_compression", "0", CVAR_RENDERERLATCH, "When enabled, blocks recognition of all compressed-texture formats. Does NOT block support for gl3 texture types like e5bgr9 nor rgba16f."); +cvar_t gl_blacklist_generatemipmap = CVARFD("gl_blacklist_generatemipmap", "1", CVAR_RENDERERLATCH, "Self-generate mipmaps, instead of letting the graphics driver do it."); float gl_anisotropy_factor; @@ -83,6 +85,10 @@ void GL_SetupFormats(void) float ver = gl_config.glversion; qboolean srgb = (gl_config.glversion >= (gl_config_gles?3.0:2.1)) || GL_CheckExtension("GL_EXT_texture_sRGB"); + memset(&gl_config.formatinfo, 0, sizeof(gl_config.formatinfo)); + memset(&sh_config.texfmt, 0, sizeof(sh_config.texfmt)); + sh_config.hw_bc = sh_config.hw_etc = sh_config.hw_astc = 0; + if (gl_config_gles && ver >= 3.0 && ver <= 3.3) ver = 3.3; //treat gles3.0 as desktop 3.3, they're roughly equivelent in feature set. @@ -90,7 +96,7 @@ void GL_SetupFormats(void) bc1=bc2=bc3=true; if ((!gl_config_gles && ver >= 3.0) || GL_CheckExtension("GL_ARB_texture_compression_rgtc") || GL_CheckExtension("GL_EXT_texture_compression_rgtc")) bc45 = true; - if ((!gl_config.gles && ver >= 4.2) || GL_CheckExtension("GL_ARB_texture_compression_bptc")) + if ((!gl_config_gles && ver >= 4.2) || GL_CheckExtension("GL_ARB_texture_compression_bptc") || GL_CheckExtension("GL_EXT_texture_compression_bptc")) bc67 = true; if (bc45) @@ -119,6 +125,15 @@ void GL_SetupFormats(void) bc2 |= GL_CheckExtension("GL_ANGLE_texture_compression_dxt3"); //WARNING: can only use these if mip0 is a multiple of 4 bc3 |= GL_CheckExtension("GL_ANGLE_texture_compression_dxt5"); +#ifdef FTE_TARGET_WEB + if (GL_CheckExtension("GL_WEBGL_compressed_texture_s3tc")) + bc1 = bc2 = bc3 = true; + if (GL_CheckExtension("GL_WEBGL_compressed_texture_s3tc")) + bc1 = bc2 = bc3 = true; +#endif + + + /*else if (sh_config.texfmt[PTI_ETC2_RGB8A8]) { //these are probably a bad choice... tc_ru = GL_COMPRESSED_R11_EAC; @@ -271,6 +286,27 @@ void GL_SetupFormats(void) } } + //provide a cvar for ignoring all texture compression extensions. + //this is more so that I can debug fallbacks. + if (gl_blacklist_texture_compression.ival) + { + Con_Printf("gl_blacklist_texture_compression: driver/hardware texture compression is "CON_WARNING"blocked"CON_DEFAULT".\n"); + return; + } + + if (bc1&&bc2&&bc3) + { + if (bc45) + { + if (bc67) + sh_config.hw_bc = 3; + else + sh_config.hw_bc = 2; + } + else + sh_config.hw_bc = 1; + } + //block compresion formats. if (bc1) { @@ -309,12 +345,14 @@ void GL_SetupFormats(void) glfmtb(PTI_BC7_RGBA_SRGB, GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM_ARB); } + if (gl_config_gles && gl_config.glversion >= 3.0 && !sh_config.hw_bc) + sh_config.hw_etc = 2; //assume that mobile chips have actual support. the bc1 check prevents this from being true on desktop chips. #ifdef FTE_TARGET_WEB - if (GL_CheckExtension("WEBGL_compressed_texture_etc")) -#else - if ((gl_config.gles && gl_config.glversion >= 3.0) || (!gl_config.gles && (gl_config.glversion >= 4.3 || GL_CheckExtension("GL_ARB_ES3_compatibility")))) + else if (GL_CheckExtension("GL_WEBGL_compressed_texture_etc")) + sh_config.hw_etc = 2; //full etc2+eac #endif - { + if (sh_config.hw_etc>=2 || (!gl_config_gles && (gl_config.glversion >= 4.3 || GL_CheckExtension("GL_ARB_ES3_compatibility")))) + { //note that desktop drivers will not necessarily support these in hardware, but are required to at least pretend that they do. glfmtb(PTI_ETC1_RGB8, GL_COMPRESSED_RGB8_ETC2); glfmtb(PTI_ETC2_RGB8, GL_COMPRESSED_RGB8_ETC2); glfmtb(PTI_ETC2_RGB8A1, GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2); @@ -351,39 +389,73 @@ void GL_SetupFormats(void) glfmtb(PTI_EAC_RG11, GL_COMPRESSED_RG11_EAC); if (GL_CheckExtension("GL_OES_compressed_EAC_RG11_signed_texture")) glfmtb(PTI_EAC_RG11_SNORM, GL_COMPRESSED_SIGNED_RG11_EAC); + + if (gl_config.formatinfo[PTI_ETC2_RGB8].internalformat && gl_config.formatinfo[PTI_EAC_RG11].internalformat && + gl_config.formatinfo[PTI_ETC2_RGB8A1].internalformat && gl_config.formatinfo[PTI_ETC2_RGB8A8].internalformat) + sh_config.hw_etc = 2; + else if (gl_config.formatinfo[PTI_ETC2_RGB8].internalformat || gl_config.formatinfo[PTI_ETC1_RGB8].internalformat) + sh_config.hw_etc = 1; } - if (GL_CheckExtension("GL_KHR_texture_compression_astc_ldr") || (gl_config_gles && gl_config.glversion >= 3.2) || GL_CheckExtension("GL_ARB_ES3_2_compatibility")) + if (GL_CheckExtension("GL_OES_texture_compression_astc")) + sh_config.hw_astc = 3; //3d textures + else if (GL_CheckExtension("GL_KHR_texture_compression_astc_hdr")) + sh_config.hw_astc = 2; //hdr textures + else if (GL_CheckExtension("GL_KHR_texture_compression_astc_ldr")) + sh_config.hw_astc = 1; //ldr textures only. +#ifdef FTE_TARGET_WEB + else if (GL_CheckExtension("GL_WEBGL_compressed_texture_astc")) + sh_config.hw_astc = 1; //need to use js getSupportedProfiles() to find the profiles, which is outside of our scope +#endif + if (sh_config.hw_astc || (gl_config_gles && gl_config.glversion >= 3.2) || GL_CheckExtension("GL_ARB_ES3_2_compatibility")) { //astc ldr profile is a core part of gles 3.2 - glfmtb(PTI_ASTC_4X4, GL_COMPRESSED_RGBA_ASTC_4x4_KHR); + //note that this does not necessarily mean the hardware itself supports it. + glfmtb(PTI_ASTC_4X4_LDR, GL_COMPRESSED_RGBA_ASTC_4x4_KHR); + glfmtb(PTI_ASTC_5X4_LDR, GL_COMPRESSED_RGBA_ASTC_5x4_KHR); + glfmtb(PTI_ASTC_5X5_LDR, GL_COMPRESSED_RGBA_ASTC_5x5_KHR); + glfmtb(PTI_ASTC_6X5_LDR, GL_COMPRESSED_RGBA_ASTC_6x5_KHR); + glfmtb(PTI_ASTC_6X6_LDR, GL_COMPRESSED_RGBA_ASTC_6x6_KHR); + glfmtb(PTI_ASTC_8X5_LDR, GL_COMPRESSED_RGBA_ASTC_8x5_KHR); + glfmtb(PTI_ASTC_8X6_LDR, GL_COMPRESSED_RGBA_ASTC_8x6_KHR); + glfmtb(PTI_ASTC_10X5_LDR, GL_COMPRESSED_RGBA_ASTC_10x5_KHR); + glfmtb(PTI_ASTC_10X6_LDR, GL_COMPRESSED_RGBA_ASTC_10x6_KHR); + glfmtb(PTI_ASTC_8X8_LDR, GL_COMPRESSED_RGBA_ASTC_8x8_KHR); + glfmtb(PTI_ASTC_10X8_LDR, GL_COMPRESSED_RGBA_ASTC_10x8_KHR); + glfmtb(PTI_ASTC_10X10_LDR, GL_COMPRESSED_RGBA_ASTC_10x10_KHR); + glfmtb(PTI_ASTC_12X10_LDR, GL_COMPRESSED_RGBA_ASTC_12x10_KHR); + glfmtb(PTI_ASTC_12X12_LDR, GL_COMPRESSED_RGBA_ASTC_12x12_KHR); glfmtb(PTI_ASTC_4X4_SRGB, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR); - glfmtb(PTI_ASTC_5X4, GL_COMPRESSED_RGBA_ASTC_5x4_KHR); glfmtb(PTI_ASTC_5X4_SRGB, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x4_KHR); - glfmtb(PTI_ASTC_5X5, GL_COMPRESSED_RGBA_ASTC_5x5_KHR); glfmtb(PTI_ASTC_5X5_SRGB, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x5_KHR); - glfmtb(PTI_ASTC_6X5, GL_COMPRESSED_RGBA_ASTC_6x5_KHR); glfmtb(PTI_ASTC_6X5_SRGB, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x5_KHR); - glfmtb(PTI_ASTC_6X6, GL_COMPRESSED_RGBA_ASTC_6x6_KHR); glfmtb(PTI_ASTC_6X6_SRGB, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x6_KHR); - glfmtb(PTI_ASTC_8X5, GL_COMPRESSED_RGBA_ASTC_8x5_KHR); glfmtb(PTI_ASTC_8X5_SRGB, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x5_KHR); - glfmtb(PTI_ASTC_8X6, GL_COMPRESSED_RGBA_ASTC_8x6_KHR); glfmtb(PTI_ASTC_8X6_SRGB, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x6_KHR); - glfmtb(PTI_ASTC_10X5, GL_COMPRESSED_RGBA_ASTC_10x5_KHR); glfmtb(PTI_ASTC_10X5_SRGB, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x5_KHR); - glfmtb(PTI_ASTC_10X6, GL_COMPRESSED_RGBA_ASTC_10x6_KHR); glfmtb(PTI_ASTC_10X6_SRGB, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x6_KHR); - glfmtb(PTI_ASTC_8X8, GL_COMPRESSED_RGBA_ASTC_8x8_KHR); glfmtb(PTI_ASTC_8X8_SRGB, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x8_KHR); - glfmtb(PTI_ASTC_10X8, GL_COMPRESSED_RGBA_ASTC_10x8_KHR); glfmtb(PTI_ASTC_10X8_SRGB, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x8_KHR); - glfmtb(PTI_ASTC_10X10, GL_COMPRESSED_RGBA_ASTC_10x10_KHR); glfmtb(PTI_ASTC_10X10_SRGB, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x10_KHR); - glfmtb(PTI_ASTC_12X10, GL_COMPRESSED_RGBA_ASTC_12x10_KHR); glfmtb(PTI_ASTC_12X10_SRGB, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x10_KHR); - glfmtb(PTI_ASTC_12X12, GL_COMPRESSED_RGBA_ASTC_12x12_KHR); glfmtb(PTI_ASTC_12X12_SRGB, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x12_KHR); } + if (sh_config.hw_astc >= 2) + { //astc hdr profile uses the same texture formats, which is kinda annoying... + glfmtb(PTI_ASTC_4X4_HDR, GL_COMPRESSED_RGBA_ASTC_4x4_KHR); + glfmtb(PTI_ASTC_5X4_HDR, GL_COMPRESSED_RGBA_ASTC_5x4_KHR); + glfmtb(PTI_ASTC_5X5_HDR, GL_COMPRESSED_RGBA_ASTC_5x5_KHR); + glfmtb(PTI_ASTC_6X5_HDR, GL_COMPRESSED_RGBA_ASTC_6x5_KHR); + glfmtb(PTI_ASTC_6X6_HDR, GL_COMPRESSED_RGBA_ASTC_6x6_KHR); + glfmtb(PTI_ASTC_8X5_HDR, GL_COMPRESSED_RGBA_ASTC_8x5_KHR); + glfmtb(PTI_ASTC_8X6_HDR, GL_COMPRESSED_RGBA_ASTC_8x6_KHR); + glfmtb(PTI_ASTC_10X5_HDR, GL_COMPRESSED_RGBA_ASTC_10x5_KHR); + glfmtb(PTI_ASTC_10X6_HDR, GL_COMPRESSED_RGBA_ASTC_10x6_KHR); + glfmtb(PTI_ASTC_8X8_HDR, GL_COMPRESSED_RGBA_ASTC_8x8_KHR); + glfmtb(PTI_ASTC_10X8_HDR, GL_COMPRESSED_RGBA_ASTC_10x8_KHR); + glfmtb(PTI_ASTC_10X10_HDR, GL_COMPRESSED_RGBA_ASTC_10x10_KHR); + glfmtb(PTI_ASTC_12X10_HDR, GL_COMPRESSED_RGBA_ASTC_12x10_KHR); + glfmtb(PTI_ASTC_12X12_HDR, GL_COMPRESSED_RGBA_ASTC_12x12_KHR); + } } /* @@ -414,6 +486,7 @@ void GLDraw_Init (void) vid.flags &= ~VID_SRGBAWARE; + sh_config.can_genmips = qglGenerateMipmap && !gl_blacklist_generatemipmap.ival; //figure out which extra features we can support on these drivers. r_deluxemapping = r_deluxemapping_cvar.ival; r_lightprepass = r_lightprepass_cvar.ival && sh_config.progs_supported; @@ -644,6 +717,8 @@ qboolean GL_LoadTextureMips(texid_t tex, const struct pendingtextureinfo *mips) qboolean compress; qboolean storage = true; unsigned int bb, bw, bh; + int levels = 0, genlevels; + int layers = 1; if (gl_config.gles) { @@ -662,17 +737,27 @@ qboolean GL_LoadTextureMips(texid_t tex, const struct pendingtextureinfo *mips) default: case 0: targ = GL_TEXTURE_2D; + layers = 1; break; case 1: targ = GL_TEXTURE_3D; + layers = 1; break; case 2: targ = GL_TEXTURE_CUBE_MAP_ARB; + layers = 1*6; break; case 3: targ = GL_TEXTURE_2D_ARRAY; + layers = 1; //TODO break; } + genlevels = levels = mips->mipcount / layers; + if (!(tex->flags & IF_NOMIPMAP) && sh_config.can_genmips && gl_config.formatinfo[encoding].type && genlevels == 1 && mips->mip[0].data && mips->encoding != PTI_P8) + { + while ((mips->mip[0].width>>genlevels) || (mips->mip[0].height>>genlevels)) + genlevels++; + } GL_MTBind(0, targ, tex); @@ -690,6 +775,10 @@ qboolean GL_LoadTextureMips(texid_t tex, const struct pendingtextureinfo *mips) GL_MTBind(0, targ, tex); } + //this is annoying. + if (mips->encoding >= PTI_ASTC_4X4_LDR && mips->encoding <= PTI_ASTC_12X12_LDR && gl_config.astc_decodeprecision) + qglTexParameteri(targ, GL_TEXTURE_ASTC_DECODE_PRECISION_EXT, GL_RGBA8); + if (tex->flags&IF_CLAMP) { if (gl_config.glversion < 1.2 && !gl_config_gles) @@ -739,13 +828,13 @@ qboolean GL_LoadTextureMips(texid_t tex, const struct pendingtextureinfo *mips) { if (tex->flags & IF_MIPCAP) { - qglTexParameteri(targ, GL_TEXTURE_BASE_LEVEL, min(nummips-1, gl_mipcap_min)); - qglTexParameteri(targ, GL_TEXTURE_MAX_LEVEL, min(nummips-1, gl_mipcap_max)); + qglTexParameteri(targ, GL_TEXTURE_BASE_LEVEL, min(genlevels-1, gl_mipcap_min)); + qglTexParameteri(targ, GL_TEXTURE_MAX_LEVEL, min(genlevels-1, gl_mipcap_max)); } else { qglTexParameteri(targ, GL_TEXTURE_BASE_LEVEL, 0); - qglTexParameteri(targ, GL_TEXTURE_MAX_LEVEL, nummips-1); + qglTexParameteri(targ, GL_TEXTURE_MAX_LEVEL, genlevels-1); } } } @@ -822,10 +911,7 @@ qboolean GL_LoadTextureMips(texid_t tex, const struct pendingtextureinfo *mips) //FIXME: support array textures properly if (qglTexStorage3D && storage) { - if (tex->flags & IF_TEXTYPE) - qglTexStorage3D(targ, nummips/countof(cubeface), ifmt, mips->mip[0].width, mips->mip[0].height, mips->mip[0].depth); - else - qglTexStorage3D(targ, nummips, ifmt, mips->mip[0].width, mips->mip[0].height, mips->mip[0].depth); + qglTexStorage3D(targ, genlevels, ifmt, mips->mip[0].width, mips->mip[0].height, mips->mip[0].depth); for (i = 0; i < nummips; i++) { @@ -848,15 +934,15 @@ qboolean GL_LoadTextureMips(texid_t tex, const struct pendingtextureinfo *mips) qglCompressedTexImage3D (targ, i, ifmt, mips->mip[i].width, mips->mip[i].height, mips->mip[0].depth, 0, mips->mip[i].datasize, mips->mip[i].data); } } + + if (genlevels > levels) + qglGenerateMipmap(targ); } else { if (qglTexStorage2D && storage) { //FIXME: destroy the old texture - if (tex->flags & IF_TEXTYPE) - qglTexStorage2D(targ, nummips/countof(cubeface), ifmt, mips->mip[0].width, mips->mip[0].height); - else - qglTexStorage2D(targ, nummips, ifmt, mips->mip[0].width, mips->mip[0].height); + qglTexStorage2D(targ, genlevels, ifmt, mips->mip[0].width, mips->mip[0].height); for (i = 0; i < nummips; i++) { @@ -902,6 +988,9 @@ qboolean GL_LoadTextureMips(texid_t tex, const struct pendingtextureinfo *mips) } } + if (genlevels > levels) + qglGenerateMipmap(targ); + #ifdef IMAGEFMT_KTX if (compress && gl_compress.ival>1 && gl_config.formatinfo[encoding].type) { @@ -944,33 +1033,33 @@ qboolean GL_LoadTextureMips(texid_t tex, const struct pendingtextureinfo *mips) case GL_COMPRESSED_SIGNED_R11_EAC: out.encoding = PTI_EAC_R11_SNORM; break; case GL_COMPRESSED_RG11_EAC: out.encoding = PTI_EAC_RG11; break; case GL_COMPRESSED_SIGNED_RG11_EAC: out.encoding = PTI_EAC_RG11_SNORM; break; - case GL_COMPRESSED_RGBA_ASTC_4x4_KHR: out.encoding = PTI_ASTC_4X4; break; + case GL_COMPRESSED_RGBA_ASTC_4x4_KHR: out.encoding = PTI_ASTC_4X4_HDR; break; //play it safe and assume hdr. case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR: out.encoding = PTI_ASTC_4X4_SRGB; break; - case GL_COMPRESSED_RGBA_ASTC_5x4_KHR: out.encoding = PTI_ASTC_5X4; break; + case GL_COMPRESSED_RGBA_ASTC_5x4_KHR: out.encoding = PTI_ASTC_5X4_HDR; break; case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x4_KHR: out.encoding = PTI_ASTC_5X4_SRGB; break; - case GL_COMPRESSED_RGBA_ASTC_5x5_KHR: out.encoding = PTI_ASTC_5X5; break; + case GL_COMPRESSED_RGBA_ASTC_5x5_KHR: out.encoding = PTI_ASTC_5X5_HDR; break; case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x5_KHR: out.encoding = PTI_ASTC_5X5_SRGB; break; - case GL_COMPRESSED_RGBA_ASTC_6x5_KHR: out.encoding = PTI_ASTC_6X5; break; + case GL_COMPRESSED_RGBA_ASTC_6x5_KHR: out.encoding = PTI_ASTC_6X5_HDR; break; case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x5_KHR: out.encoding = PTI_ASTC_6X5_SRGB; break; - case GL_COMPRESSED_RGBA_ASTC_6x6_KHR: out.encoding = PTI_ASTC_6X6; break; + case GL_COMPRESSED_RGBA_ASTC_6x6_KHR: out.encoding = PTI_ASTC_6X6_HDR; break; case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x6_KHR: out.encoding = PTI_ASTC_6X6_SRGB; break; - case GL_COMPRESSED_RGBA_ASTC_8x5_KHR: out.encoding = PTI_ASTC_8X5; break; + case GL_COMPRESSED_RGBA_ASTC_8x5_KHR: out.encoding = PTI_ASTC_8X5_HDR; break; case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x5_KHR: out.encoding = PTI_ASTC_8X5_SRGB; break; - case GL_COMPRESSED_RGBA_ASTC_8x6_KHR: out.encoding = PTI_ASTC_8X6; break; + case GL_COMPRESSED_RGBA_ASTC_8x6_KHR: out.encoding = PTI_ASTC_8X6_HDR; break; case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x6_KHR: out.encoding = PTI_ASTC_8X6_SRGB; break; - case GL_COMPRESSED_RGBA_ASTC_10x5_KHR: out.encoding = PTI_ASTC_10X5; break; + case GL_COMPRESSED_RGBA_ASTC_10x5_KHR: out.encoding = PTI_ASTC_10X5_HDR; break; case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x5_KHR: out.encoding = PTI_ASTC_10X5_SRGB; break; - case GL_COMPRESSED_RGBA_ASTC_10x6_KHR: out.encoding = PTI_ASTC_10X6; break; + case GL_COMPRESSED_RGBA_ASTC_10x6_KHR: out.encoding = PTI_ASTC_10X6_HDR; break; case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x6_KHR: out.encoding = PTI_ASTC_10X6_SRGB; break; - case GL_COMPRESSED_RGBA_ASTC_8x8_KHR: out.encoding = PTI_ASTC_8X8; break; + case GL_COMPRESSED_RGBA_ASTC_8x8_KHR: out.encoding = PTI_ASTC_8X8_HDR; break; case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x8_KHR: out.encoding = PTI_ASTC_8X8_SRGB; break; - case GL_COMPRESSED_RGBA_ASTC_10x8_KHR: out.encoding = PTI_ASTC_10X8; break; + case GL_COMPRESSED_RGBA_ASTC_10x8_KHR: out.encoding = PTI_ASTC_10X8_HDR; break; case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x8_KHR: out.encoding = PTI_ASTC_10X8_SRGB; break; - case GL_COMPRESSED_RGBA_ASTC_10x10_KHR: out.encoding = PTI_ASTC_10X10; break; + case GL_COMPRESSED_RGBA_ASTC_10x10_KHR: out.encoding = PTI_ASTC_10X10_HDR; break; case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x10_KHR: out.encoding = PTI_ASTC_10X10_SRGB; break; - case GL_COMPRESSED_RGBA_ASTC_12x10_KHR: out.encoding = PTI_ASTC_12X10; break; + case GL_COMPRESSED_RGBA_ASTC_12x10_KHR: out.encoding = PTI_ASTC_12X10_HDR; break; case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x10_KHR: out.encoding = PTI_ASTC_12X10_SRGB; break; - case GL_COMPRESSED_RGBA_ASTC_12x12_KHR: out.encoding = PTI_ASTC_12X12; break; + case GL_COMPRESSED_RGBA_ASTC_12x12_KHR: out.encoding = PTI_ASTC_12X12_HDR; break; case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x12_KHR: out.encoding = PTI_ASTC_12X12_SRGB; break; } diff --git a/engine/gl/gl_heightmap.c b/engine/gl/gl_heightmap.c index be6a1458f..0447f8b0d 100644 --- a/engine/gl/gl_heightmap.c +++ b/engine/gl/gl_heightmap.c @@ -28,6 +28,8 @@ cvar_t mod_terrain_sundir = CVARD("mod_terrain_sundir", "0.4 0.7 2", "The direct cvar_t mod_terrain_ambient = CVARD("mod_terrain_ambient", "0.5", "Proportion of ambient light."); cvar_t mod_terrain_shadows = CVARD("mod_terrain_shadows", "0", "Cast rays to determine whether parts of the terrain should be in shadow."); cvar_t mod_terrain_shadow_dist = CVARD("mod_terrain_shadow_dist", "2048", "How far rays should be cast in order to look for occlusing geometry."); +cvar_t mod_terrain_brushlights = CVARD("mod_map_lights", "0", "Calculates lighting on brushes/patches."); +cvar_t mod_terrain_brushtexscale = CVARD("mod_map_texscale", "1", "Defines the scale of texture texels. Use 1 for quake+quake2 maps, and 0.5 for quake3 maps."); enum { @@ -5546,7 +5548,8 @@ void Terr_Brush_Draw(heightmap_t *hm, batch_t **batches, entity_t *e) if (mod->submodelof) mod = mod->submodelof; hm->entsdirty = false; - LightReloadEntities(hm->relightcontext, Mod_GetEntitiesString(mod), true); + if (hm->relightcontext) + LightReloadEntities(hm->relightcontext, Mod_GetEntitiesString(mod), true); //FIXME: figure out some way to hint this without having to relight the entire frigging world. for (bt = hm->brushtextures; bt; bt = bt->next) @@ -5835,11 +5838,15 @@ void Terr_Brush_Draw(heightmap_t *hm, batch_t **batches, entity_t *e) const miptex_t *tx = NULL; #endif - if (!Q_strcasecmp(bt->shadername, "clip") || !Q_strcasecmp(bt->shadername, "hint") || !Q_strcasecmp(bt->shadername, "skip")) - bt->shader = R_RegisterShader(bt->shadername, SUF_LIGHTMAP, "{\nsurfaceparm nodraw\n}"); - else - bt->shader = R_RegisterCustom (bt->shadername, SUF_LIGHTMAP, Shader_DefaultBSPQ1, NULL); -// bt->shader = R_RegisterShader_Lightmap(bt->shadername); + bt->shader = R_RegisterCustom (va("textures/%s", bt->shadername), SUF_LIGHTMAP, NULL, NULL); + if (!bt->shader) + { + if (!Q_strcasecmp(bt->shadername, "clip") || !Q_strcasecmp(bt->shadername, "hint") || !Q_strcasecmp(bt->shadername, "skip")) + bt->shader = R_RegisterShader(bt->shadername, SUF_LIGHTMAP, "{\nsurfaceparm nodraw\n}"); + else + bt->shader = R_RegisterCustom (bt->shadername, SUF_LIGHTMAP, Shader_DefaultBSPQ1, NULL); +// bt->shader = R_RegisterShader_Lightmap(bt->shadername); + } if (!Q_strncasecmp(bt->shadername, "sky", 3) && tx) R_InitSky (bt->shader, bt->shadername, (qbyte*)tx + tx->offsets[0], tx->width, tx->height); @@ -5871,8 +5878,8 @@ void Terr_Brush_Draw(heightmap_t *hm, batch_t **batches, entity_t *e) if (w<1) w = 64; if (h<1) h = 64; - scale[0] = 1.0/w; //I hate needing this. - scale[1] = 1.0/h; + scale[0] = mod_terrain_brushtexscale.value/w; //I hate needing this. + scale[1] = mod_terrain_brushtexscale.value/h; while(bt->batches) { @@ -7411,7 +7418,7 @@ qboolean Terr_ReformEntitiesLump(model_t *mod, heightmap_t *hm, char *entities) #ifdef RUNTIMELIGHTING hm->entsdirty = true; - hm->relightcontext = LightStartup(NULL, mod, false, false); + hm->relightcontext = mod_terrain_brushlights.ival?LightStartup(NULL, mod, mod_terrain_brushlights.ival>1, false):NULL; hm->lightthreadmem = BZ_Malloc(lightthreadctxsize); hm->inheritedlightthreadmem = false; #endif @@ -8480,6 +8487,8 @@ void Terr_Init(void) Cvar_Register(&mod_terrain_ambient, "Terrain"); Cvar_Register(&mod_terrain_shadows, "Terrain"); Cvar_Register(&mod_terrain_shadow_dist, "Terrain"); + Cvar_Register(&mod_terrain_brushlights, "Terrain"); + Cvar_Register(&mod_terrain_brushtexscale, "Terrain"); #endif Mod_RegisterModelFormatText(NULL, "FTE Heightmap Map (hmp)", "terrain", Terr_LoadTerrainModel); diff --git a/engine/gl/gl_shader.c b/engine/gl/gl_shader.c index 8718fe2e2..1ef843a01 100644 --- a/engine/gl/gl_shader.c +++ b/engine/gl/gl_shader.c @@ -681,8 +681,12 @@ static void Shader_ParseFunc (shader_t *shader, char **ptr, shaderfunc_t *func) func->type = SHADER_FUNC_INVERSESAWTOOTH; else if (!Q_stricmp (token, "noise")) func->type = SHADER_FUNC_NOISE; - else if (!Q_stricmp (token, "distanceramp")) //QFusion + else { + if (!Q_stricmp (token, "distanceramp")) //QFusion + ; + else + Con_Printf("Shader_ParseFunc: %s: unknown func %s\n", shader->name, token); func->type = SHADER_FUNC_CONSTANT; //not supported... Shader_ParseFloat (shader, ptr, 0); Shader_ParseFloat (shader, ptr, 0); diff --git a/engine/gl/gl_shadow.c b/engine/gl/gl_shadow.c index 1254c5cbc..4ea86692b 100644 --- a/engine/gl/gl_shadow.c +++ b/engine/gl/gl_shadow.c @@ -2939,7 +2939,7 @@ static void Sh_DrawBrushModelShadow(dlight_t *dl, entity_t *e) //front face qglVertexPointer(3, GL_FLOAT, sizeof(vecV_t), surf->mesh->xyz_array); qglDrawArrays(GL_POLYGON, 0, surf->mesh->numvertexes); -// qglDrawRangeElements(GL_TRIANGLES, 0, surf->mesh->numvertexes, surf->mesh->numindexes, GL_INDEX_TYPE, surf->mesh->indexes); +// qglDrawRangeElements(GL_TRIANGLES, 0, surf->mesh->numvertexes-1, surf->mesh->numindexes, GL_INDEX_TYPE, surf->mesh->indexes); RQuantAdd(RQUANT_SHADOWINDICIES, surf->mesh->numvertexes); for (v = 0; v < surf->mesh->numvertexes; v++) diff --git a/engine/gl/gl_vidcommon.c b/engine/gl/gl_vidcommon.c index a69123675..4150604cc 100644 --- a/engine/gl/gl_vidcommon.c +++ b/engine/gl/gl_vidcommon.c @@ -50,6 +50,7 @@ void (APIENTRY *qglEnable) (GLenum cap); void (APIENTRY *qglFinish) (void); void (APIENTRY *qglFlush) (void); void (APIENTRY *qglGenTextures) (GLsizei n, GLuint *textures); +void (APIENTRY *qglGenerateMipmap)(GLenum target); void (APIENTRY *qglGetBooleanv) (GLenum pname, GLboolean *params); GLenum (APIENTRY *qglGetError) (void); void (APIENTRY *qglGetFloatv) (GLenum pname, GLfloat *params); @@ -862,6 +863,8 @@ void GL_CheckExtensions (void *(*getglfunction) (char *name)) gl_config.arb_texture_compression = true; } #endif + + gl_config.astc_decodeprecision = GL_CheckExtension("GL_EXT_texture_compression_astc_decode_mode"); /* if (GL_CheckExtension("GL_EXT_depth_bounds_test")) qglDepthBoundsEXT = (void *)getglext("glDepthBoundsEXT"); @@ -3349,6 +3352,11 @@ qboolean GL_Init(rendererstate_t *info, void *(*getglfunction) (char *name)) GL_CheckExtensions (getglfunction); + if (gl_config.glversion >= 3.0) + qglGenerateMipmap = (void *)getglext("glGenerateMipmap"); + else + qglGenerateMipmap = NULL; + #ifndef FTE_TARGET_WEB if (!gl_config.gles) { diff --git a/engine/gl/gl_warp.c b/engine/gl/gl_warp.c index 1e80ed162..745c98c74 100644 --- a/engine/gl/gl_warp.c +++ b/engine/gl/gl_warp.c @@ -195,7 +195,7 @@ qboolean R_DrawSkyroom(shader_t *skyshader) //q3 mustn't mask sky (breaks q3map2's invisible skyportals), whereas q1 must (or its a cheat). halflife doesn't normally expect masking. //we also MUST mask any sky inside skyrooms, or you'll see all the entities outside of the skyroom through the room's own sky (q3map2 skyportals are hopefully irrelevant in this case). -#define SKYMUSTBEMASKED (r_worldentity.model->fromgame != fg_quake3 || ((r_refdef.flags & RDF_DISABLEPARTICLES) && !r_ignoreentpvs.ival)) +#define SKYMUSTBEMASKED (r_worldentity.model->fromgame != fg_quake3 || ((r_refdef.flags & RDF_DISABLEPARTICLES) && r_ignoreentpvs.ival)) /* ================= diff --git a/engine/gl/glquake.h b/engine/gl/glquake.h index 87bf635dc..34b7075a0 100644 --- a/engine/gl/glquake.h +++ b/engine/gl/glquake.h @@ -235,6 +235,7 @@ typedef struct { qboolean arb_texture_env_dot3; qboolean arb_texture_compression; //means we support dynamic compression, rather than any specific compressed texture formats + qboolean astc_decodeprecision; //means we can tell the gpu that our astc textures actually are ldr. qboolean geometryshaders; qboolean arb_tessellation_shader; @@ -652,6 +653,7 @@ extern void (APIENTRY *qglFinish) (void); extern void (APIENTRY *qglFlush) (void); extern void (APIENTRY *qglFrontFace) (GLenum mode); extern void (APIENTRY *qglGenTextures) (GLsizei n, GLuint *textures); +extern void (APIENTRY *qglGenerateMipmap)(GLenum target); extern void (APIENTRY *qglGetBooleanv) (GLenum pname, GLboolean *params); extern GLenum (APIENTRY *qglGetError) (void); extern void (APIENTRY *qglGetFloatv) (GLenum pname, GLfloat *params); diff --git a/engine/gl/glsupp.h b/engine/gl/glsupp.h index 937c5b69f..8e1d89833 100644 --- a/engine/gl/glsupp.h +++ b/engine/gl/glsupp.h @@ -682,9 +682,11 @@ typedef void (APIENTRYP PFNGLGETSHADERSOURCEARBPROC) (GLhandleARB obj, GLsizei #define GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT 0x8C4F #endif /* GL_EXT_texture_sRGB */ +#ifndef GL_RGB9_E5 +#define GL_RGB9_E5 0x8C3D /*opengl 3.0*/ +#endif #ifndef GL_RG #define GL_RG 0x8227 -#define GL_RGB9_E5 0x8C3D /*opengl 3.0*/ #define GL_R8 0x8229 /*opengl 3.0*/ #define GL_R16 0x822A /*opengl 3.0*/ #define GL_RG8 0x822B /*opengl 3.0*/ @@ -811,7 +813,9 @@ typedef void (APIENTRY * PFNGLUNLOCKARRAYSEXTPROC) (void); #endif - +#ifndef GL_EXT_texture_compression_astc_decode_mode +#define GL_TEXTURE_ASTC_DECODE_PRECISION_EXT 0x8F69 +#endif #ifndef GL_EXT_framebuffer_object #define GL_INVALID_FRAMEBUFFER_OPERATION_EXT 0x0506 diff --git a/engine/gl/r_bishaders.h b/engine/gl/r_bishaders.h index cb769d1e3..3ee9251b7 100644 --- a/engine/gl/r_bishaders.h +++ b/engine/gl/r_bishaders.h @@ -6012,680 +6012,630 @@ YOU SHOULD NOT EDIT THIS FILE BY HAND #endif #ifdef VKQUAKE {QR_VULKAN, -1, "defaultwall", -"\xFF\x53\x50\x56\x01\x00\x00\x00\x9C\x37\x00\x00\x01\x00\x00\x00\x2B\x00\x00\x00\x2C\x00\x00\x00\xA6\x00\x00\x00\xD4\x00\x00\x00" -"\x48\x16\x00\x00\x1C\x17\x00\x00\x20\x3D\x00\x00\x01\x00\x66\x31\x72\x5F\x67\x6C\x73\x6C\x5F\x6F\x66\x66\x73\x65\x74\x6D\x61\x70" +"\xFF\x53\x50\x56\x01\x00\x00\x00\x9C\x36\x00\x00\x00\x00\x00\x00\x2B\x00\x00\x00\x2C\x00\x00\x00\x95\x00\x00\x00\xC4\x00\x00\x00" +"\x10\x16\x00\x00\xD4\x16\x00\x00\x24\x37\x00\x00\x01\x00\x66\x31\x72\x5F\x67\x6C\x73\x6C\x5F\x6F\x66\x66\x73\x65\x74\x6D\x61\x70" "\x70\x69\x6E\x67\x00\x00\x00\x00\x00\x01\x01\x66\x31\x72\x5F\x67\x6C\x73\x6C\x5F\x6F\x66\x66\x73\x65\x74\x6D\x61\x70\x70\x69\x6E" "\x67\x5F\x73\x63\x61\x6C\x65\x00\x3D\x23\xD7\x0A\x01\x02\x66\x31\x67\x6C\x5F\x73\x70\x65\x63\x75\x6C\x61\x72\x00\x3E\x99\x99\x9A" "\x01\x03\x62\x31\x72\x5F\x66\x6F\x67\x5F\x65\x78\x70\x32\x00\x00\x00\x00\x00\x01\x04\x42\x31\x76\x65\x72\x74\x65\x78\x6C\x69\x74" -"\x00\x00\x00\x00\x00\x01\x05\x42\x31\x65\x69\x67\x68\x74\x62\x69\x74\x00\x00\x00\x00\x00\x01\x06\x46\x31\x6D\x61\x73\x6B\x00\x3F" -"\x80\x00\x00\x01\x07\x42\x31\x6D\x61\x73\x6B\x6C\x74\x00\x00\x00\x00\x00\x00\x00\x03\x02\x23\x07\x00\x00\x01\x00\x06\x00\x08\x00" -"\x8F\x00\x00\x00\x00\x00\x00\x00\x11\x00\x02\x00\x01\x00\x00\x00\x0B\x00\x06\x00\x01\x00\x00\x00\x47\x4C\x53\x4C\x2E\x73\x74\x64" -"\x2E\x34\x35\x30\x00\x00\x00\x00\x0E\x00\x03\x00\x00\x00\x00\x00\x01\x00\x00\x00\x0F\x00\x12\x00\x00\x00\x00\x00\x04\x00\x00\x00" -"\x6D\x61\x69\x6E\x00\x00\x00\x00\x1C\x00\x00\x00\x4D\x00\x00\x00\x4F\x00\x00\x00\x56\x00\x00\x00\x5B\x00\x00\x00\x64\x00\x00\x00" -"\x6E\x00\x00\x00\x70\x00\x00\x00\x72\x00\x00\x00\x73\x00\x00\x00\x7A\x00\x00\x00\x7C\x00\x00\x00\x80\x00\x00\x00\x03\x00\x03\x00" -"\x02\x00\x00\x00\xC2\x01\x00\x00\x05\x00\x04\x00\x04\x00\x00\x00\x6D\x61\x69\x6E\x00\x00\x00\x00\x05\x00\x06\x00\x09\x00\x00\x00" -"\x66\x74\x65\x74\x72\x61\x6E\x73\x66\x6F\x72\x6D\x28\x00\x00\x00\x05\x00\x04\x00\x0C\x00\x00\x00\x70\x72\x6F\x6A\x00\x00\x00\x00" -"\x05\x00\x05\x00\x13\x00\x00\x00\x65\x6E\x74\x69\x74\x79\x62\x6C\x6F\x63\x6B\x00\x06\x00\x07\x00\x13\x00\x00\x00\x00\x00\x00\x00" -"\x6D\x5F\x6D\x6F\x64\x65\x6C\x76\x69\x65\x77\x70\x72\x6F\x6A\x00\x06\x00\x05\x00\x13\x00\x00\x00\x01\x00\x00\x00\x6D\x5F\x6D\x6F" -"\x64\x65\x6C\x00\x06\x00\x06\x00\x13\x00\x00\x00\x02\x00\x00\x00\x6D\x5F\x6D\x6F\x64\x65\x6C\x69\x6E\x76\x00\x00\x06\x00\x06\x00" -"\x13\x00\x00\x00\x03\x00\x00\x00\x65\x5F\x65\x79\x65\x70\x6F\x73\x00\x00\x00\x00\x06\x00\x05\x00\x13\x00\x00\x00\x04\x00\x00\x00" -"\x65\x5F\x74\x69\x6D\x65\x00\x00\x06\x00\x07\x00\x13\x00\x00\x00\x05\x00\x00\x00\x65\x5F\x6C\x69\x67\x68\x74\x5F\x61\x6D\x62\x69" -"\x65\x6E\x74\x00\x06\x00\x05\x00\x13\x00\x00\x00\x06\x00\x00\x00\x65\x70\x61\x64\x31\x00\x00\x00\x06\x00\x06\x00\x13\x00\x00\x00" -"\x07\x00\x00\x00\x65\x5F\x6C\x69\x67\x68\x74\x5F\x64\x69\x72\x00\x06\x00\x05\x00\x13\x00\x00\x00\x08\x00\x00\x00\x65\x70\x61\x64" -"\x32\x00\x00\x00\x06\x00\x06\x00\x13\x00\x00\x00\x09\x00\x00\x00\x65\x5F\x6C\x69\x67\x68\x74\x5F\x6D\x75\x6C\x00\x06\x00\x05\x00" -"\x13\x00\x00\x00\x0A\x00\x00\x00\x65\x70\x61\x64\x33\x00\x00\x00\x06\x00\x06\x00\x13\x00\x00\x00\x0B\x00\x00\x00\x65\x5F\x6C\x6D" -"\x73\x63\x61\x6C\x65\x73\x00\x00\x06\x00\x07\x00\x13\x00\x00\x00\x0C\x00\x00\x00\x65\x5F\x75\x70\x70\x65\x72\x63\x6F\x6C\x6F\x75" -"\x72\x00\x00\x00\x06\x00\x05\x00\x13\x00\x00\x00\x0D\x00\x00\x00\x65\x70\x61\x64\x34\x00\x00\x00\x06\x00\x07\x00\x13\x00\x00\x00" -"\x0E\x00\x00\x00\x65\x5F\x6C\x6F\x77\x65\x72\x63\x6F\x6C\x6F\x75\x72\x00\x00\x00\x06\x00\x05\x00\x13\x00\x00\x00\x0F\x00\x00\x00" -"\x65\x70\x61\x64\x35\x00\x00\x00\x06\x00\x06\x00\x13\x00\x00\x00\x10\x00\x00\x00\x65\x5F\x67\x6C\x6F\x77\x6D\x6F\x64\x00\x00\x00" -"\x06\x00\x05\x00\x13\x00\x00\x00\x11\x00\x00\x00\x65\x70\x61\x64\x36\x00\x00\x00\x06\x00\x07\x00\x13\x00\x00\x00\x12\x00\x00\x00" -"\x65\x5F\x63\x6F\x6C\x6F\x75\x72\x69\x64\x65\x6E\x74\x00\x00\x00\x06\x00\x07\x00\x13\x00\x00\x00\x13\x00\x00\x00\x77\x5F\x66\x6F" -"\x67\x63\x6F\x6C\x6F\x75\x72\x73\x00\x00\x00\x00\x06\x00\x07\x00\x13\x00\x00\x00\x14\x00\x00\x00\x77\x5F\x66\x6F\x67\x64\x65\x6E" -"\x73\x69\x74\x79\x00\x00\x00\x00\x06\x00\x07\x00\x13\x00\x00\x00\x15\x00\x00\x00\x77\x5F\x66\x6F\x67\x64\x65\x70\x74\x68\x62\x69" -"\x61\x73\x00\x00\x06\x00\x05\x00\x13\x00\x00\x00\x16\x00\x00\x00\x65\x70\x61\x64\x37\x00\x00\x00\x05\x00\x03\x00\x15\x00\x00\x00" -"\x00\x00\x00\x00\x05\x00\x05\x00\x1C\x00\x00\x00\x76\x5F\x70\x6F\x73\x69\x74\x69\x6F\x6E\x00\x00\x05\x00\x09\x00\x38\x00\x00\x00" -"\x63\x76\x61\x72\x5F\x72\x5F\x67\x6C\x73\x6C\x5F\x6F\x66\x66\x73\x65\x74\x6D\x61\x70\x70\x69\x6E\x67\x00\x00\x00\x05\x00\x07\x00" -"\x3C\x00\x00\x00\x63\x76\x61\x72\x5F\x67\x6C\x5F\x73\x70\x65\x63\x75\x6C\x61\x72\x00\x00\x00\x00\x05\x00\x07\x00\x3F\x00\x00\x00" -"\x5F\x52\x45\x46\x4C\x45\x43\x54\x43\x55\x42\x45\x4D\x41\x53\x4B\x00\x00\x00\x00\x05\x00\x06\x00\x45\x00\x00\x00\x65\x79\x65\x6D" -"\x69\x6E\x75\x73\x76\x65\x72\x74\x65\x78\x00\x00\x05\x00\x05\x00\x4D\x00\x00\x00\x65\x79\x65\x76\x65\x63\x74\x6F\x72\x00\x00\x00" -"\x05\x00\x05\x00\x4F\x00\x00\x00\x76\x5F\x73\x76\x65\x63\x74\x6F\x72\x00\x00\x00\x05\x00\x05\x00\x56\x00\x00\x00\x76\x5F\x74\x76" -"\x65\x63\x74\x6F\x72\x00\x00\x00\x05\x00\x05\x00\x5B\x00\x00\x00\x76\x5F\x6E\x6F\x72\x6D\x61\x6C\x00\x00\x00\x00\x05\x00\x05\x00" -"\x64\x00\x00\x00\x69\x6E\x76\x73\x75\x72\x66\x61\x63\x65\x00\x00\x05\x00\x04\x00\x6E\x00\x00\x00\x62\x61\x73\x65\x74\x63\x00\x00" -"\x05\x00\x05\x00\x70\x00\x00\x00\x76\x5F\x74\x65\x78\x63\x6F\x6F\x72\x64\x00\x00\x05\x00\x03\x00\x72\x00\x00\x00\x6C\x6D\x30\x00" -"\x05\x00\x05\x00\x73\x00\x00\x00\x76\x5F\x6C\x6D\x63\x6F\x6F\x72\x64\x00\x00\x00\x05\x00\x06\x00\x75\x00\x00\x00\x5F\x61\x72\x67" -"\x5F\x76\x65\x72\x74\x65\x78\x6C\x69\x74\x00\x00\x05\x00\x03\x00\x7A\x00\x00\x00\x76\x63\x00\x00\x05\x00\x05\x00\x7C\x00\x00\x00" -"\x76\x5F\x63\x6F\x6C\x6F\x75\x72\x00\x00\x00\x00\x05\x00\x06\x00\x7E\x00\x00\x00\x67\x6C\x5F\x50\x65\x72\x56\x65\x72\x74\x65\x78" -"\x00\x00\x00\x00\x06\x00\x06\x00\x7E\x00\x00\x00\x00\x00\x00\x00\x67\x6C\x5F\x50\x6F\x73\x69\x74\x69\x6F\x6E\x00\x05\x00\x03\x00" -"\x80\x00\x00\x00\x00\x00\x00\x00\x05\x00\x0A\x00\x83\x00\x00\x00\x63\x76\x61\x72\x5F\x72\x5F\x67\x6C\x73\x6C\x5F\x6F\x66\x66\x73" -"\x65\x74\x6D\x61\x70\x70\x69\x6E\x67\x5F\x73\x63\x61\x6C\x65\x00\x05\x00\x07\x00\x84\x00\x00\x00\x5F\x63\x76\x61\x72\x5F\x72\x5F" -"\x66\x6F\x67\x5F\x65\x78\x70\x32\x00\x00\x00\x00\x05\x00\x06\x00\x85\x00\x00\x00\x5F\x61\x72\x67\x5F\x65\x69\x67\x68\x74\x62\x69" -"\x74\x00\x00\x00\x05\x00\x05\x00\x86\x00\x00\x00\x61\x72\x67\x5F\x6D\x61\x73\x6B\x00\x00\x00\x00\x05\x00\x05\x00\x87\x00\x00\x00" -"\x5F\x61\x72\x67\x5F\x6D\x61\x73\x6B\x6C\x74\x00\x05\x00\x04\x00\x88\x00\x00\x00\x5F\x42\x55\x4D\x50\x00\x00\x00\x05\x00\x05\x00" -"\x89\x00\x00\x00\x5F\x46\x55\x4C\x4C\x42\x52\x49\x47\x48\x54\x00\x05\x00\x04\x00\x8A\x00\x00\x00\x5F\x46\x4F\x47\x00\x00\x00\x00" -"\x05\x00\x05\x00\x8C\x00\x00\x00\x6C\x69\x67\x68\x74\x62\x6C\x6F\x63\x6B\x00\x00\x06\x00\x07\x00\x8C\x00\x00\x00\x00\x00\x00\x00" -"\x6C\x5F\x63\x75\x62\x65\x6D\x61\x74\x72\x69\x78\x00\x00\x00\x00\x06\x00\x07\x00\x8C\x00\x00\x00\x01\x00\x00\x00\x6C\x5F\x6C\x69" -"\x67\x68\x74\x70\x6F\x73\x69\x74\x69\x6F\x6E\x00\x06\x00\x05\x00\x8C\x00\x00\x00\x02\x00\x00\x00\x6C\x70\x61\x64\x31\x00\x00\x00" -"\x06\x00\x07\x00\x8C\x00\x00\x00\x03\x00\x00\x00\x6C\x5F\x6C\x69\x67\x68\x74\x63\x6F\x6C\x6F\x75\x72\x00\x00\x00\x06\x00\x05\x00" -"\x8C\x00\x00\x00\x04\x00\x00\x00\x6C\x70\x61\x64\x32\x00\x00\x00\x06\x00\x08\x00\x8C\x00\x00\x00\x05\x00\x00\x00\x6C\x5F\x6C\x69" -"\x67\x68\x74\x63\x6F\x6C\x6F\x75\x72\x73\x63\x61\x6C\x65\x00\x00\x06\x00\x07\x00\x8C\x00\x00\x00\x06\x00\x00\x00\x6C\x5F\x6C\x69" -"\x67\x68\x74\x72\x61\x64\x69\x75\x73\x00\x00\x00\x06\x00\x07\x00\x8C\x00\x00\x00\x07\x00\x00\x00\x6C\x5F\x73\x68\x61\x64\x6F\x77" -"\x6D\x61\x70\x70\x72\x6F\x6A\x00\x06\x00\x08\x00\x8C\x00\x00\x00\x08\x00\x00\x00\x6C\x5F\x73\x68\x61\x64\x6F\x77\x6D\x61\x70\x73" -"\x63\x61\x6C\x65\x00\x00\x00\x00\x06\x00\x05\x00\x8C\x00\x00\x00\x09\x00\x00\x00\x6C\x70\x61\x64\x33\x00\x00\x00\x05\x00\x03\x00" -"\x8E\x00\x00\x00\x00\x00\x00\x00\x47\x00\x04\x00\x11\x00\x00\x00\x06\x00\x00\x00\x10\x00\x00\x00\x48\x00\x04\x00\x13\x00\x00\x00" -"\x00\x00\x00\x00\x05\x00\x00\x00\x48\x00\x05\x00\x13\x00\x00\x00\x00\x00\x00\x00\x23\x00\x00\x00\x00\x00\x00\x00\x48\x00\x05\x00" -"\x13\x00\x00\x00\x00\x00\x00\x00\x07\x00\x00\x00\x10\x00\x00\x00\x48\x00\x04\x00\x13\x00\x00\x00\x01\x00\x00\x00\x05\x00\x00\x00" -"\x48\x00\x05\x00\x13\x00\x00\x00\x01\x00\x00\x00\x23\x00\x00\x00\x40\x00\x00\x00\x48\x00\x05\x00\x13\x00\x00\x00\x01\x00\x00\x00" -"\x07\x00\x00\x00\x10\x00\x00\x00\x48\x00\x04\x00\x13\x00\x00\x00\x02\x00\x00\x00\x05\x00\x00\x00\x48\x00\x05\x00\x13\x00\x00\x00" -"\x02\x00\x00\x00\x23\x00\x00\x00\x80\x00\x00\x00\x48\x00\x05\x00\x13\x00\x00\x00\x02\x00\x00\x00\x07\x00\x00\x00\x10\x00\x00\x00" -"\x48\x00\x05\x00\x13\x00\x00\x00\x03\x00\x00\x00\x23\x00\x00\x00\xC0\x00\x00\x00\x48\x00\x05\x00\x13\x00\x00\x00\x04\x00\x00\x00" -"\x23\x00\x00\x00\xCC\x00\x00\x00\x48\x00\x05\x00\x13\x00\x00\x00\x05\x00\x00\x00\x23\x00\x00\x00\xD0\x00\x00\x00\x48\x00\x05\x00" -"\x13\x00\x00\x00\x06\x00\x00\x00\x23\x00\x00\x00\xDC\x00\x00\x00\x48\x00\x05\x00\x13\x00\x00\x00\x07\x00\x00\x00\x23\x00\x00\x00" -"\xE0\x00\x00\x00\x48\x00\x05\x00\x13\x00\x00\x00\x08\x00\x00\x00\x23\x00\x00\x00\xEC\x00\x00\x00\x48\x00\x05\x00\x13\x00\x00\x00" -"\x09\x00\x00\x00\x23\x00\x00\x00\xF0\x00\x00\x00\x48\x00\x05\x00\x13\x00\x00\x00\x0A\x00\x00\x00\x23\x00\x00\x00\xFC\x00\x00\x00" -"\x48\x00\x05\x00\x13\x00\x00\x00\x0B\x00\x00\x00\x23\x00\x00\x00\x00\x01\x00\x00\x48\x00\x05\x00\x13\x00\x00\x00\x0C\x00\x00\x00" -"\x23\x00\x00\x00\x40\x01\x00\x00\x48\x00\x05\x00\x13\x00\x00\x00\x0D\x00\x00\x00\x23\x00\x00\x00\x4C\x01\x00\x00\x48\x00\x05\x00" -"\x13\x00\x00\x00\x0E\x00\x00\x00\x23\x00\x00\x00\x50\x01\x00\x00\x48\x00\x05\x00\x13\x00\x00\x00\x0F\x00\x00\x00\x23\x00\x00\x00" -"\x5C\x01\x00\x00\x48\x00\x05\x00\x13\x00\x00\x00\x10\x00\x00\x00\x23\x00\x00\x00\x60\x01\x00\x00\x48\x00\x05\x00\x13\x00\x00\x00" -"\x11\x00\x00\x00\x23\x00\x00\x00\x6C\x01\x00\x00\x48\x00\x05\x00\x13\x00\x00\x00\x12\x00\x00\x00\x23\x00\x00\x00\x70\x01\x00\x00" -"\x48\x00\x05\x00\x13\x00\x00\x00\x13\x00\x00\x00\x23\x00\x00\x00\x80\x01\x00\x00\x48\x00\x05\x00\x13\x00\x00\x00\x14\x00\x00\x00" -"\x23\x00\x00\x00\x90\x01\x00\x00\x48\x00\x05\x00\x13\x00\x00\x00\x15\x00\x00\x00\x23\x00\x00\x00\x94\x01\x00\x00\x48\x00\x05\x00" -"\x13\x00\x00\x00\x16\x00\x00\x00\x23\x00\x00\x00\x98\x01\x00\x00\x47\x00\x03\x00\x13\x00\x00\x00\x02\x00\x00\x00\x47\x00\x04\x00" -"\x15\x00\x00\x00\x22\x00\x00\x00\x00\x00\x00\x00\x47\x00\x04\x00\x15\x00\x00\x00\x21\x00\x00\x00\x00\x00\x00\x00\x47\x00\x04\x00" -"\x1C\x00\x00\x00\x1E\x00\x00\x00\x00\x00\x00\x00\x47\x00\x04\x00\x38\x00\x00\x00\x01\x00\x00\x00\x00\x01\x00\x00\x47\x00\x04\x00" -"\x3C\x00\x00\x00\x01\x00\x00\x00\x02\x01\x00\x00\x47\x00\x04\x00\x3F\x00\x00\x00\x01\x00\x00\x00\x13\x00\x00\x00\x47\x00\x04\x00" -"\x4D\x00\x00\x00\x1E\x00\x00\x00\x01\x00\x00\x00\x47\x00\x04\x00\x4F\x00\x00\x00\x1E\x00\x00\x00\x05\x00\x00\x00\x47\x00\x04\x00" -"\x56\x00\x00\x00\x1E\x00\x00\x00\x06\x00\x00\x00\x47\x00\x04\x00\x5B\x00\x00\x00\x1E\x00\x00\x00\x04\x00\x00\x00\x47\x00\x04\x00" -"\x64\x00\x00\x00\x1E\x00\x00\x00\x04\x00\x00\x00\x47\x00\x04\x00\x6E\x00\x00\x00\x1E\x00\x00\x00\x02\x00\x00\x00\x47\x00\x04\x00" -"\x70\x00\x00\x00\x1E\x00\x00\x00\x01\x00\x00\x00\x47\x00\x04\x00\x72\x00\x00\x00\x1E\x00\x00\x00\x00\x00\x00\x00\x47\x00\x04\x00" -"\x73\x00\x00\x00\x1E\x00\x00\x00\x03\x00\x00\x00\x47\x00\x04\x00\x75\x00\x00\x00\x01\x00\x00\x00\x04\x01\x00\x00\x47\x00\x04\x00" -"\x7A\x00\x00\x00\x1E\x00\x00\x00\x03\x00\x00\x00\x47\x00\x04\x00\x7C\x00\x00\x00\x1E\x00\x00\x00\x02\x00\x00\x00\x48\x00\x05\x00" -"\x7E\x00\x00\x00\x00\x00\x00\x00\x0B\x00\x00\x00\x00\x00\x00\x00\x47\x00\x03\x00\x7E\x00\x00\x00\x02\x00\x00\x00\x47\x00\x04\x00" -"\x83\x00\x00\x00\x01\x00\x00\x00\x01\x01\x00\x00\x47\x00\x04\x00\x84\x00\x00\x00\x01\x00\x00\x00\x03\x01\x00\x00\x47\x00\x04\x00" -"\x85\x00\x00\x00\x01\x00\x00\x00\x05\x01\x00\x00\x47\x00\x04\x00\x86\x00\x00\x00\x01\x00\x00\x00\x06\x01\x00\x00\x47\x00\x04\x00" -"\x87\x00\x00\x00\x01\x00\x00\x00\x07\x01\x00\x00\x47\x00\x04\x00\x88\x00\x00\x00\x01\x00\x00\x00\x10\x00\x00\x00\x47\x00\x04\x00" -"\x89\x00\x00\x00\x01\x00\x00\x00\x11\x00\x00\x00\x47\x00\x04\x00\x8A\x00\x00\x00\x01\x00\x00\x00\x15\x00\x00\x00\x48\x00\x04\x00" -"\x8C\x00\x00\x00\x00\x00\x00\x00\x05\x00\x00\x00\x48\x00\x05\x00\x8C\x00\x00\x00\x00\x00\x00\x00\x23\x00\x00\x00\x00\x00\x00\x00" -"\x48\x00\x05\x00\x8C\x00\x00\x00\x00\x00\x00\x00\x07\x00\x00\x00\x10\x00\x00\x00\x48\x00\x05\x00\x8C\x00\x00\x00\x01\x00\x00\x00" -"\x23\x00\x00\x00\x40\x00\x00\x00\x48\x00\x05\x00\x8C\x00\x00\x00\x02\x00\x00\x00\x23\x00\x00\x00\x4C\x00\x00\x00\x48\x00\x05\x00" -"\x8C\x00\x00\x00\x03\x00\x00\x00\x23\x00\x00\x00\x50\x00\x00\x00\x48\x00\x05\x00\x8C\x00\x00\x00\x04\x00\x00\x00\x23\x00\x00\x00" -"\x5C\x00\x00\x00\x48\x00\x05\x00\x8C\x00\x00\x00\x05\x00\x00\x00\x23\x00\x00\x00\x60\x00\x00\x00\x48\x00\x05\x00\x8C\x00\x00\x00" -"\x06\x00\x00\x00\x23\x00\x00\x00\x6C\x00\x00\x00\x48\x00\x05\x00\x8C\x00\x00\x00\x07\x00\x00\x00\x23\x00\x00\x00\x70\x00\x00\x00" -"\x48\x00\x05\x00\x8C\x00\x00\x00\x08\x00\x00\x00\x23\x00\x00\x00\x80\x00\x00\x00\x48\x00\x05\x00\x8C\x00\x00\x00\x09\x00\x00\x00" -"\x23\x00\x00\x00\x88\x00\x00\x00\x47\x00\x03\x00\x8C\x00\x00\x00\x02\x00\x00\x00\x47\x00\x04\x00\x8E\x00\x00\x00\x22\x00\x00\x00" -"\x00\x00\x00\x00\x47\x00\x04\x00\x8E\x00\x00\x00\x21\x00\x00\x00\x01\x00\x00\x00\x13\x00\x02\x00\x02\x00\x00\x00\x21\x00\x03\x00" -"\x03\x00\x00\x00\x02\x00\x00\x00\x16\x00\x03\x00\x06\x00\x00\x00\x20\x00\x00\x00\x17\x00\x04\x00\x07\x00\x00\x00\x06\x00\x00\x00" -"\x04\x00\x00\x00\x21\x00\x03\x00\x08\x00\x00\x00\x07\x00\x00\x00\x20\x00\x04\x00\x0B\x00\x00\x00\x07\x00\x00\x00\x07\x00\x00\x00" -"\x18\x00\x04\x00\x0D\x00\x00\x00\x07\x00\x00\x00\x04\x00\x00\x00\x17\x00\x04\x00\x0E\x00\x00\x00\x06\x00\x00\x00\x03\x00\x00\x00" -"\x15\x00\x04\x00\x0F\x00\x00\x00\x20\x00\x00\x00\x00\x00\x00\x00\x2B\x00\x04\x00\x0F\x00\x00\x00\x10\x00\x00\x00\x04\x00\x00\x00" -"\x1C\x00\x04\x00\x11\x00\x00\x00\x07\x00\x00\x00\x10\x00\x00\x00\x17\x00\x04\x00\x12\x00\x00\x00\x06\x00\x00\x00\x02\x00\x00\x00" -"\x1E\x00\x19\x00\x13\x00\x00\x00\x0D\x00\x00\x00\x0D\x00\x00\x00\x0D\x00\x00\x00\x0E\x00\x00\x00\x06\x00\x00\x00\x0E\x00\x00\x00" -"\x06\x00\x00\x00\x0E\x00\x00\x00\x06\x00\x00\x00\x0E\x00\x00\x00\x06\x00\x00\x00\x11\x00\x00\x00\x0E\x00\x00\x00\x06\x00\x00\x00" -"\x0E\x00\x00\x00\x06\x00\x00\x00\x0E\x00\x00\x00\x06\x00\x00\x00\x07\x00\x00\x00\x07\x00\x00\x00\x06\x00\x00\x00\x06\x00\x00\x00" -"\x12\x00\x00\x00\x20\x00\x04\x00\x14\x00\x00\x00\x02\x00\x00\x00\x13\x00\x00\x00\x3B\x00\x04\x00\x14\x00\x00\x00\x15\x00\x00\x00" -"\x02\x00\x00\x00\x15\x00\x04\x00\x16\x00\x00\x00\x20\x00\x00\x00\x01\x00\x00\x00\x2B\x00\x04\x00\x16\x00\x00\x00\x17\x00\x00\x00" -"\x00\x00\x00\x00\x20\x00\x04\x00\x18\x00\x00\x00\x02\x00\x00\x00\x0D\x00\x00\x00\x20\x00\x04\x00\x1B\x00\x00\x00\x01\x00\x00\x00" -"\x0E\x00\x00\x00\x3B\x00\x04\x00\x1B\x00\x00\x00\x1C\x00\x00\x00\x01\x00\x00\x00\x2B\x00\x04\x00\x06\x00\x00\x00\x1E\x00\x00\x00" -"\x00\x00\x80\x3F\x2B\x00\x04\x00\x06\x00\x00\x00\x24\x00\x00\x00\x00\x00\x80\xBF\x2B\x00\x04\x00\x0F\x00\x00\x00\x25\x00\x00\x00" -"\x01\x00\x00\x00\x20\x00\x04\x00\x26\x00\x00\x00\x07\x00\x00\x00\x06\x00\x00\x00\x2B\x00\x04\x00\x0F\x00\x00\x00\x2B\x00\x00\x00" -"\x02\x00\x00\x00\x2B\x00\x04\x00\x0F\x00\x00\x00\x2E\x00\x00\x00\x03\x00\x00\x00\x2B\x00\x04\x00\x06\x00\x00\x00\x32\x00\x00\x00" -"\x00\x00\x00\x40\x32\x00\x04\x00\x06\x00\x00\x00\x38\x00\x00\x00\x00\x00\x80\x43\x2B\x00\x04\x00\x06\x00\x00\x00\x39\x00\x00\x00" -"\x00\x00\x00\x00\x14\x00\x02\x00\x3A\x00\x00\x00\x32\x00\x04\x00\x06\x00\x00\x00\x3C\x00\x00\x00\x00\x00\x81\x43\x32\x00\x04\x00" -"\x16\x00\x00\x00\x3F\x00\x00\x00\x13\x00\x00\x00\x34\x00\x06\x00\x3A\x00\x00\x00\x40\x00\x00\x00\xAB\x00\x00\x00\x3F\x00\x00\x00" -"\x17\x00\x00\x00\x20\x00\x04\x00\x44\x00\x00\x00\x07\x00\x00\x00\x0E\x00\x00\x00\x2B\x00\x04\x00\x16\x00\x00\x00\x46\x00\x00\x00" -"\x03\x00\x00\x00\x20\x00\x04\x00\x47\x00\x00\x00\x02\x00\x00\x00\x0E\x00\x00\x00\x20\x00\x04\x00\x4C\x00\x00\x00\x03\x00\x00\x00" -"\x0E\x00\x00\x00\x3B\x00\x04\x00\x4C\x00\x00\x00\x4D\x00\x00\x00\x03\x00\x00\x00\x3B\x00\x04\x00\x1B\x00\x00\x00\x4F\x00\x00\x00" -"\x01\x00\x00\x00\x2B\x00\x04\x00\x0F\x00\x00\x00\x52\x00\x00\x00\x00\x00\x00\x00\x20\x00\x04\x00\x53\x00\x00\x00\x03\x00\x00\x00" -"\x06\x00\x00\x00\x3B\x00\x04\x00\x1B\x00\x00\x00\x56\x00\x00\x00\x01\x00\x00\x00\x3B\x00\x04\x00\x1B\x00\x00\x00\x5B\x00\x00\x00" -"\x01\x00\x00\x00\x34\x00\x06\x00\x3A\x00\x00\x00\x5F\x00\x00\x00\xAB\x00\x00\x00\x3F\x00\x00\x00\x17\x00\x00\x00\x18\x00\x04\x00" -"\x62\x00\x00\x00\x0E\x00\x00\x00\x03\x00\x00\x00\x20\x00\x04\x00\x63\x00\x00\x00\x03\x00\x00\x00\x62\x00\x00\x00\x3B\x00\x04\x00" -"\x63\x00\x00\x00\x64\x00\x00\x00\x03\x00\x00\x00\x2B\x00\x04\x00\x16\x00\x00\x00\x67\x00\x00\x00\x01\x00\x00\x00\x2B\x00\x04\x00" -"\x16\x00\x00\x00\x6A\x00\x00\x00\x02\x00\x00\x00\x20\x00\x04\x00\x6D\x00\x00\x00\x03\x00\x00\x00\x12\x00\x00\x00\x3B\x00\x04\x00" -"\x6D\x00\x00\x00\x6E\x00\x00\x00\x03\x00\x00\x00\x20\x00\x04\x00\x6F\x00\x00\x00\x01\x00\x00\x00\x12\x00\x00\x00\x3B\x00\x04\x00" -"\x6F\x00\x00\x00\x70\x00\x00\x00\x01\x00\x00\x00\x3B\x00\x04\x00\x6D\x00\x00\x00\x72\x00\x00\x00\x03\x00\x00\x00\x3B\x00\x04\x00" -"\x6F\x00\x00\x00\x73\x00\x00\x00\x01\x00\x00\x00\x32\x00\x04\x00\x16\x00\x00\x00\x75\x00\x00\x00\x04\x01\x00\x00\x34\x00\x06\x00" -"\x3A\x00\x00\x00\x76\x00\x00\x00\xAB\x00\x00\x00\x75\x00\x00\x00\x17\x00\x00\x00\x20\x00\x04\x00\x79\x00\x00\x00\x03\x00\x00\x00" -"\x07\x00\x00\x00\x3B\x00\x04\x00\x79\x00\x00\x00\x7A\x00\x00\x00\x03\x00\x00\x00\x20\x00\x04\x00\x7B\x00\x00\x00\x01\x00\x00\x00" -"\x07\x00\x00\x00\x3B\x00\x04\x00\x7B\x00\x00\x00\x7C\x00\x00\x00\x01\x00\x00\x00\x1E\x00\x03\x00\x7E\x00\x00\x00\x07\x00\x00\x00" -"\x20\x00\x04\x00\x7F\x00\x00\x00\x03\x00\x00\x00\x7E\x00\x00\x00\x3B\x00\x04\x00\x7F\x00\x00\x00\x80\x00\x00\x00\x03\x00\x00\x00" -"\x32\x00\x04\x00\x06\x00\x00\x00\x83\x00\x00\x00\x00\x80\x80\x43\x32\x00\x04\x00\x16\x00\x00\x00\x84\x00\x00\x00\x03\x01\x00\x00" -"\x32\x00\x04\x00\x16\x00\x00\x00\x85\x00\x00\x00\x05\x01\x00\x00\x32\x00\x04\x00\x06\x00\x00\x00\x86\x00\x00\x00\x00\x00\x83\x43" -"\x32\x00\x04\x00\x16\x00\x00\x00\x87\x00\x00\x00\x07\x01\x00\x00\x32\x00\x04\x00\x16\x00\x00\x00\x88\x00\x00\x00\x10\x00\x00\x00" -"\x32\x00\x04\x00\x16\x00\x00\x00\x89\x00\x00\x00\x11\x00\x00\x00\x32\x00\x04\x00\x16\x00\x00\x00\x8A\x00\x00\x00\x15\x00\x00\x00" -"\x2A\x00\x03\x00\x3A\x00\x00\x00\x8B\x00\x00\x00\x1E\x00\x0C\x00\x8C\x00\x00\x00\x0D\x00\x00\x00\x0E\x00\x00\x00\x06\x00\x00\x00" -"\x0E\x00\x00\x00\x06\x00\x00\x00\x0E\x00\x00\x00\x06\x00\x00\x00\x07\x00\x00\x00\x12\x00\x00\x00\x12\x00\x00\x00\x20\x00\x04\x00" -"\x8D\x00\x00\x00\x02\x00\x00\x00\x8C\x00\x00\x00\x3B\x00\x04\x00\x8D\x00\x00\x00\x8E\x00\x00\x00\x02\x00\x00\x00\x36\x00\x05\x00" -"\x02\x00\x00\x00\x04\x00\x00\x00\x00\x00\x00\x00\x03\x00\x00\x00\xF8\x00\x02\x00\x05\x00\x00\x00\x3B\x00\x04\x00\x44\x00\x00\x00" -"\x45\x00\x00\x00\x07\x00\x00\x00\xBA\x00\x05\x00\x3A\x00\x00\x00\x3B\x00\x00\x00\x38\x00\x00\x00\x39\x00\x00\x00\xBA\x00\x05\x00" -"\x3A\x00\x00\x00\x3D\x00\x00\x00\x3C\x00\x00\x00\x39\x00\x00\x00\xA6\x00\x05\x00\x3A\x00\x00\x00\x3E\x00\x00\x00\x3B\x00\x00\x00" -"\x3D\x00\x00\x00\xA6\x00\x05\x00\x3A\x00\x00\x00\x41\x00\x00\x00\x3E\x00\x00\x00\x40\x00\x00\x00\xF7\x00\x03\x00\x43\x00\x00\x00" -"\x00\x00\x00\x00\xFA\x00\x04\x00\x41\x00\x00\x00\x42\x00\x00\x00\x43\x00\x00\x00\xF8\x00\x02\x00\x42\x00\x00\x00\x41\x00\x05\x00" -"\x47\x00\x00\x00\x48\x00\x00\x00\x15\x00\x00\x00\x46\x00\x00\x00\x3D\x00\x04\x00\x0E\x00\x00\x00\x49\x00\x00\x00\x48\x00\x00\x00" -"\x3D\x00\x04\x00\x0E\x00\x00\x00\x4A\x00\x00\x00\x1C\x00\x00\x00\x83\x00\x05\x00\x0E\x00\x00\x00\x4B\x00\x00\x00\x49\x00\x00\x00" -"\x4A\x00\x00\x00\x3E\x00\x03\x00\x45\x00\x00\x00\x4B\x00\x00\x00\x3D\x00\x04\x00\x0E\x00\x00\x00\x4E\x00\x00\x00\x45\x00\x00\x00" -"\x3D\x00\x04\x00\x0E\x00\x00\x00\x50\x00\x00\x00\x4F\x00\x00\x00\x94\x00\x05\x00\x06\x00\x00\x00\x51\x00\x00\x00\x4E\x00\x00\x00" -"\x50\x00\x00\x00\x41\x00\x05\x00\x53\x00\x00\x00\x54\x00\x00\x00\x4D\x00\x00\x00\x52\x00\x00\x00\x3E\x00\x03\x00\x54\x00\x00\x00" -"\x51\x00\x00\x00\x3D\x00\x04\x00\x0E\x00\x00\x00\x55\x00\x00\x00\x45\x00\x00\x00\x3D\x00\x04\x00\x0E\x00\x00\x00\x57\x00\x00\x00" -"\x56\x00\x00\x00\x94\x00\x05\x00\x06\x00\x00\x00\x58\x00\x00\x00\x55\x00\x00\x00\x57\x00\x00\x00\x41\x00\x05\x00\x53\x00\x00\x00" -"\x59\x00\x00\x00\x4D\x00\x00\x00\x25\x00\x00\x00\x3E\x00\x03\x00\x59\x00\x00\x00\x58\x00\x00\x00\x3D\x00\x04\x00\x0E\x00\x00\x00" -"\x5A\x00\x00\x00\x45\x00\x00\x00\x3D\x00\x04\x00\x0E\x00\x00\x00\x5C\x00\x00\x00\x5B\x00\x00\x00\x94\x00\x05\x00\x06\x00\x00\x00" -"\x5D\x00\x00\x00\x5A\x00\x00\x00\x5C\x00\x00\x00\x41\x00\x05\x00\x53\x00\x00\x00\x5E\x00\x00\x00\x4D\x00\x00\x00\x2B\x00\x00\x00" -"\x3E\x00\x03\x00\x5E\x00\x00\x00\x5D\x00\x00\x00\xF9\x00\x02\x00\x43\x00\x00\x00\xF8\x00\x02\x00\x43\x00\x00\x00\xF7\x00\x03\x00" -"\x61\x00\x00\x00\x00\x00\x00\x00\xFA\x00\x04\x00\x5F\x00\x00\x00\x60\x00\x00\x00\x61\x00\x00\x00\xF8\x00\x02\x00\x60\x00\x00\x00" -"\x3D\x00\x04\x00\x0E\x00\x00\x00\x65\x00\x00\x00\x4F\x00\x00\x00\x41\x00\x05\x00\x4C\x00\x00\x00\x66\x00\x00\x00\x64\x00\x00\x00" -"\x17\x00\x00\x00\x3E\x00\x03\x00\x66\x00\x00\x00\x65\x00\x00\x00\x3D\x00\x04\x00\x0E\x00\x00\x00\x68\x00\x00\x00\x56\x00\x00\x00" -"\x41\x00\x05\x00\x4C\x00\x00\x00\x69\x00\x00\x00\x64\x00\x00\x00\x67\x00\x00\x00\x3E\x00\x03\x00\x69\x00\x00\x00\x68\x00\x00\x00" -"\x3D\x00\x04\x00\x0E\x00\x00\x00\x6B\x00\x00\x00\x5B\x00\x00\x00\x41\x00\x05\x00\x4C\x00\x00\x00\x6C\x00\x00\x00\x64\x00\x00\x00" -"\x6A\x00\x00\x00\x3E\x00\x03\x00\x6C\x00\x00\x00\x6B\x00\x00\x00\xF9\x00\x02\x00\x61\x00\x00\x00\xF8\x00\x02\x00\x61\x00\x00\x00" -"\x3D\x00\x04\x00\x12\x00\x00\x00\x71\x00\x00\x00\x70\x00\x00\x00\x3E\x00\x03\x00\x6E\x00\x00\x00\x71\x00\x00\x00\x3D\x00\x04\x00" -"\x12\x00\x00\x00\x74\x00\x00\x00\x73\x00\x00\x00\x3E\x00\x03\x00\x72\x00\x00\x00\x74\x00\x00\x00\xF7\x00\x03\x00\x78\x00\x00\x00" -"\x00\x00\x00\x00\xFA\x00\x04\x00\x76\x00\x00\x00\x77\x00\x00\x00\x78\x00\x00\x00\xF8\x00\x02\x00\x77\x00\x00\x00\x3D\x00\x04\x00" -"\x07\x00\x00\x00\x7D\x00\x00\x00\x7C\x00\x00\x00\x3E\x00\x03\x00\x7A\x00\x00\x00\x7D\x00\x00\x00\xF9\x00\x02\x00\x78\x00\x00\x00" -"\xF8\x00\x02\x00\x78\x00\x00\x00\x39\x00\x04\x00\x07\x00\x00\x00\x81\x00\x00\x00\x09\x00\x00\x00\x41\x00\x05\x00\x79\x00\x00\x00" -"\x82\x00\x00\x00\x80\x00\x00\x00\x17\x00\x00\x00\x3E\x00\x03\x00\x82\x00\x00\x00\x81\x00\x00\x00\xFD\x00\x01\x00\x38\x00\x01\x00" -"\x36\x00\x05\x00\x07\x00\x00\x00\x09\x00\x00\x00\x00\x00\x00\x00\x08\x00\x00\x00\xF8\x00\x02\x00\x0A\x00\x00\x00\x3B\x00\x04\x00" -"\x0B\x00\x00\x00\x0C\x00\x00\x00\x07\x00\x00\x00\x41\x00\x05\x00\x18\x00\x00\x00\x19\x00\x00\x00\x15\x00\x00\x00\x17\x00\x00\x00" -"\x3D\x00\x04\x00\x0D\x00\x00\x00\x1A\x00\x00\x00\x19\x00\x00\x00\x3D\x00\x04\x00\x0E\x00\x00\x00\x1D\x00\x00\x00\x1C\x00\x00\x00" -"\x51\x00\x05\x00\x06\x00\x00\x00\x1F\x00\x00\x00\x1D\x00\x00\x00\x00\x00\x00\x00\x51\x00\x05\x00\x06\x00\x00\x00\x20\x00\x00\x00" -"\x1D\x00\x00\x00\x01\x00\x00\x00\x51\x00\x05\x00\x06\x00\x00\x00\x21\x00\x00\x00\x1D\x00\x00\x00\x02\x00\x00\x00\x50\x00\x07\x00" -"\x07\x00\x00\x00\x22\x00\x00\x00\x1F\x00\x00\x00\x20\x00\x00\x00\x21\x00\x00\x00\x1E\x00\x00\x00\x91\x00\x05\x00\x07\x00\x00\x00" -"\x23\x00\x00\x00\x1A\x00\x00\x00\x22\x00\x00\x00\x3E\x00\x03\x00\x0C\x00\x00\x00\x23\x00\x00\x00\x41\x00\x05\x00\x26\x00\x00\x00" -"\x27\x00\x00\x00\x0C\x00\x00\x00\x25\x00\x00\x00\x3D\x00\x04\x00\x06\x00\x00\x00\x28\x00\x00\x00\x27\x00\x00\x00\x85\x00\x05\x00" -"\x06\x00\x00\x00\x29\x00\x00\x00\x28\x00\x00\x00\x24\x00\x00\x00\x41\x00\x05\x00\x26\x00\x00\x00\x2A\x00\x00\x00\x0C\x00\x00\x00" -"\x25\x00\x00\x00\x3E\x00\x03\x00\x2A\x00\x00\x00\x29\x00\x00\x00\x41\x00\x05\x00\x26\x00\x00\x00\x2C\x00\x00\x00\x0C\x00\x00\x00" -"\x2B\x00\x00\x00\x3D\x00\x04\x00\x06\x00\x00\x00\x2D\x00\x00\x00\x2C\x00\x00\x00\x41\x00\x05\x00\x26\x00\x00\x00\x2F\x00\x00\x00" -"\x0C\x00\x00\x00\x2E\x00\x00\x00\x3D\x00\x04\x00\x06\x00\x00\x00\x30\x00\x00\x00\x2F\x00\x00\x00\x81\x00\x05\x00\x06\x00\x00\x00" -"\x31\x00\x00\x00\x2D\x00\x00\x00\x30\x00\x00\x00\x88\x00\x05\x00\x06\x00\x00\x00\x33\x00\x00\x00\x31\x00\x00\x00\x32\x00\x00\x00" -"\x41\x00\x05\x00\x26\x00\x00\x00\x34\x00\x00\x00\x0C\x00\x00\x00\x2B\x00\x00\x00\x3E\x00\x03\x00\x34\x00\x00\x00\x33\x00\x00\x00" -"\x3D\x00\x04\x00\x07\x00\x00\x00\x35\x00\x00\x00\x0C\x00\x00\x00\xFE\x00\x02\x00\x35\x00\x00\x00\x38\x00\x01\x00\x03\x02\x23\x07" -"\x00\x00\x01\x00\x06\x00\x08\x00\x47\x02\x00\x00\x00\x00\x00\x00\x11\x00\x02\x00\x01\x00\x00\x00\x0B\x00\x06\x00\x01\x00\x00\x00" -"\x47\x4C\x53\x4C\x2E\x73\x74\x64\x2E\x34\x35\x30\x00\x00\x00\x00\x0E\x00\x03\x00\x00\x00\x00\x00\x01\x00\x00\x00\x0F\x00\x0C\x00" -"\x04\x00\x00\x00\x04\x00\x00\x00\x6D\x61\x69\x6E\x00\x00\x00\x00\x36\x00\x00\x00\x03\x01\x00\x00\x0A\x01\x00\x00\x11\x01\x00\x00" -"\x38\x01\x00\x00\x46\x01\x00\x00\xB5\x01\x00\x00\x10\x00\x03\x00\x04\x00\x00\x00\x07\x00\x00\x00\x03\x00\x03\x00\x02\x00\x00\x00" -"\xC2\x01\x00\x00\x05\x00\x04\x00\x04\x00\x00\x00\x6D\x61\x69\x6E\x00\x00\x00\x00\x05\x00\x05\x00\x0B\x00\x00\x00\x66\x6F\x67\x33" -"\x28\x76\x66\x33\x3B\x00\x00\x00\x05\x00\x06\x00\x0A\x00\x00\x00\x72\x65\x67\x75\x6C\x61\x72\x63\x6F\x6C\x6F\x75\x72\x00\x00\x00" -"\x05\x00\x05\x00\x11\x00\x00\x00\x66\x6F\x67\x34\x28\x76\x66\x34\x3B\x00\x00\x00\x05\x00\x06\x00\x10\x00\x00\x00\x72\x65\x67\x75" -"\x6C\x61\x72\x63\x6F\x6C\x6F\x75\x72\x00\x00\x00\x05\x00\x08\x00\x1C\x00\x00\x00\x6F\x66\x66\x73\x65\x74\x6D\x61\x70\x28\x73\x32" -"\x31\x3B\x76\x66\x32\x3B\x76\x66\x33\x3B\x00\x00\x05\x00\x04\x00\x19\x00\x00\x00\x6E\x6F\x72\x6D\x74\x65\x78\x00\x05\x00\x04\x00" -"\x1A\x00\x00\x00\x62\x61\x73\x65\x00\x00\x00\x00\x05\x00\x05\x00\x1B\x00\x00\x00\x65\x79\x65\x76\x65\x63\x74\x6F\x72\x00\x00\x00" -"\x05\x00\x04\x00\x1F\x00\x00\x00\x5F\x46\x4F\x47\x00\x00\x00\x00\x05\x00\x03\x00\x29\x00\x00\x00\x7A\x00\x00\x00\x05\x00\x05\x00" -"\x2E\x00\x00\x00\x65\x6E\x74\x69\x74\x79\x62\x6C\x6F\x63\x6B\x00\x06\x00\x07\x00\x2E\x00\x00\x00\x00\x00\x00\x00\x6D\x5F\x6D\x6F" -"\x64\x65\x6C\x76\x69\x65\x77\x70\x72\x6F\x6A\x00\x06\x00\x05\x00\x2E\x00\x00\x00\x01\x00\x00\x00\x6D\x5F\x6D\x6F\x64\x65\x6C\x00" -"\x06\x00\x06\x00\x2E\x00\x00\x00\x02\x00\x00\x00\x6D\x5F\x6D\x6F\x64\x65\x6C\x69\x6E\x76\x00\x00\x06\x00\x06\x00\x2E\x00\x00\x00" -"\x03\x00\x00\x00\x65\x5F\x65\x79\x65\x70\x6F\x73\x00\x00\x00\x00\x06\x00\x05\x00\x2E\x00\x00\x00\x04\x00\x00\x00\x65\x5F\x74\x69" -"\x6D\x65\x00\x00\x06\x00\x07\x00\x2E\x00\x00\x00\x05\x00\x00\x00\x65\x5F\x6C\x69\x67\x68\x74\x5F\x61\x6D\x62\x69\x65\x6E\x74\x00" -"\x06\x00\x05\x00\x2E\x00\x00\x00\x06\x00\x00\x00\x65\x70\x61\x64\x31\x00\x00\x00\x06\x00\x06\x00\x2E\x00\x00\x00\x07\x00\x00\x00" -"\x65\x5F\x6C\x69\x67\x68\x74\x5F\x64\x69\x72\x00\x06\x00\x05\x00\x2E\x00\x00\x00\x08\x00\x00\x00\x65\x70\x61\x64\x32\x00\x00\x00" -"\x06\x00\x06\x00\x2E\x00\x00\x00\x09\x00\x00\x00\x65\x5F\x6C\x69\x67\x68\x74\x5F\x6D\x75\x6C\x00\x06\x00\x05\x00\x2E\x00\x00\x00" -"\x0A\x00\x00\x00\x65\x70\x61\x64\x33\x00\x00\x00\x06\x00\x06\x00\x2E\x00\x00\x00\x0B\x00\x00\x00\x65\x5F\x6C\x6D\x73\x63\x61\x6C" -"\x65\x73\x00\x00\x06\x00\x07\x00\x2E\x00\x00\x00\x0C\x00\x00\x00\x65\x5F\x75\x70\x70\x65\x72\x63\x6F\x6C\x6F\x75\x72\x00\x00\x00" -"\x06\x00\x05\x00\x2E\x00\x00\x00\x0D\x00\x00\x00\x65\x70\x61\x64\x34\x00\x00\x00\x06\x00\x07\x00\x2E\x00\x00\x00\x0E\x00\x00\x00" -"\x65\x5F\x6C\x6F\x77\x65\x72\x63\x6F\x6C\x6F\x75\x72\x00\x00\x00\x06\x00\x05\x00\x2E\x00\x00\x00\x0F\x00\x00\x00\x65\x70\x61\x64" -"\x35\x00\x00\x00\x06\x00\x06\x00\x2E\x00\x00\x00\x10\x00\x00\x00\x65\x5F\x67\x6C\x6F\x77\x6D\x6F\x64\x00\x00\x00\x06\x00\x05\x00" -"\x2E\x00\x00\x00\x11\x00\x00\x00\x65\x70\x61\x64\x36\x00\x00\x00\x06\x00\x07\x00\x2E\x00\x00\x00\x12\x00\x00\x00\x65\x5F\x63\x6F" -"\x6C\x6F\x75\x72\x69\x64\x65\x6E\x74\x00\x00\x00\x06\x00\x07\x00\x2E\x00\x00\x00\x13\x00\x00\x00\x77\x5F\x66\x6F\x67\x63\x6F\x6C" -"\x6F\x75\x72\x73\x00\x00\x00\x00\x06\x00\x07\x00\x2E\x00\x00\x00\x14\x00\x00\x00\x77\x5F\x66\x6F\x67\x64\x65\x6E\x73\x69\x74\x79" -"\x00\x00\x00\x00\x06\x00\x07\x00\x2E\x00\x00\x00\x15\x00\x00\x00\x77\x5F\x66\x6F\x67\x64\x65\x70\x74\x68\x62\x69\x61\x73\x00\x00" -"\x06\x00\x05\x00\x2E\x00\x00\x00\x16\x00\x00\x00\x65\x70\x61\x64\x37\x00\x00\x00\x05\x00\x03\x00\x30\x00\x00\x00\x00\x00\x00\x00" -"\x05\x00\x06\x00\x36\x00\x00\x00\x67\x6C\x5F\x46\x72\x61\x67\x43\x6F\x6F\x72\x64\x00\x00\x00\x00\x05\x00\x07\x00\x47\x00\x00\x00" -"\x5F\x63\x76\x61\x72\x5F\x72\x5F\x66\x6F\x67\x5F\x65\x78\x70\x32\x00\x00\x00\x00\x05\x00\x03\x00\x4E\x00\x00\x00\x66\x61\x63\x00" -"\x05\x00\x04\x00\x6F\x00\x00\x00\x70\x61\x72\x61\x6D\x00\x00\x00\x05\x00\x06\x00\x7F\x00\x00\x00\x4F\x66\x66\x73\x65\x74\x56\x65" -"\x63\x74\x6F\x72\x00\x00\x00\x00\x05\x00\x0A\x00\x83\x00\x00\x00\x63\x76\x61\x72\x5F\x72\x5F\x67\x6C\x73\x6C\x5F\x6F\x66\x66\x73" -"\x65\x74\x6D\x61\x70\x70\x69\x6E\x67\x5F\x73\x63\x61\x6C\x65\x00\x05\x00\x03\x00\x8C\x00\x00\x00\x52\x54\x00\x00\x05\x00\x03\x00" -"\x98\x00\x00\x00\x69\x00\x00\x00\x05\x00\x03\x00\xAE\x00\x00\x00\x66\x00\x00\x00\x05\x00\x09\x00\xD1\x00\x00\x00\x63\x76\x61\x72" -"\x5F\x72\x5F\x67\x6C\x73\x6C\x5F\x6F\x66\x66\x73\x65\x74\x6D\x61\x70\x70\x69\x6E\x67\x00\x00\x00\x05\x00\x06\x00\xD5\x00\x00\x00" -"\x4F\x66\x66\x73\x65\x74\x56\x65\x63\x74\x6F\x72\x00\x00\x00\x00\x05\x00\x03\x00\xDC\x00\x00\x00\x74\x63\x00\x00\x05\x00\x03\x00" -"\x01\x01\x00\x00\x74\x63\x00\x00\x05\x00\x04\x00\x03\x01\x00\x00\x62\x61\x73\x65\x74\x63\x00\x00\x05\x00\x05\x00\x08\x01\x00\x00" -"\x73\x5F\x6E\x6F\x72\x6D\x61\x6C\x6D\x61\x70\x00\x05\x00\x05\x00\x0A\x01\x00\x00\x65\x79\x65\x76\x65\x63\x74\x6F\x72\x00\x00\x00" -"\x05\x00\x04\x00\x0B\x01\x00\x00\x70\x61\x72\x61\x6D\x00\x00\x00\x05\x00\x04\x00\x0D\x01\x00\x00\x70\x61\x72\x61\x6D\x00\x00\x00" -"\x05\x00\x05\x00\x11\x01\x00\x00\x6F\x75\x74\x63\x6F\x6C\x6F\x75\x72\x00\x00\x00\x05\x00\x05\x00\x12\x01\x00\x00\x73\x5F\x64\x69" -"\x66\x66\x75\x73\x65\x00\x00\x00\x05\x00\x04\x00\x16\x01\x00\x00\x5F\x42\x55\x4D\x50\x00\x00\x00\x05\x00\x07\x00\x1A\x01\x00\x00" -"\x63\x76\x61\x72\x5F\x67\x6C\x5F\x73\x70\x65\x63\x75\x6C\x61\x72\x00\x00\x00\x00\x05\x00\x07\x00\x1D\x01\x00\x00\x5F\x52\x45\x46" -"\x4C\x45\x43\x54\x43\x55\x42\x45\x4D\x41\x53\x4B\x00\x00\x00\x00\x05\x00\x04\x00\x23\x01\x00\x00\x6E\x6F\x72\x6D\x00\x00\x00\x00" -"\x05\x00\x06\x00\x33\x01\x00\x00\x5F\x61\x72\x67\x5F\x76\x65\x72\x74\x65\x78\x6C\x69\x74\x00\x00\x05\x00\x05\x00\x37\x01\x00\x00" -"\x6C\x69\x67\x68\x74\x6D\x61\x70\x73\x00\x00\x00\x05\x00\x03\x00\x38\x01\x00\x00\x76\x63\x00\x00\x05\x00\x06\x00\x41\x01\x00\x00" -"\x5F\x61\x72\x67\x5F\x65\x69\x67\x68\x74\x62\x69\x74\x00\x00\x00\x05\x00\x05\x00\x45\x01\x00\x00\x6E\x65\x61\x72\x65\x73\x74\x6C" -"\x6D\x30\x00\x00\x05\x00\x03\x00\x46\x01\x00\x00\x6C\x6D\x30\x00\x05\x00\x05\x00\x50\x01\x00\x00\x73\x5F\x6C\x69\x67\x68\x74\x6D" -"\x61\x70\x00\x00\x05\x00\x04\x00\x62\x01\x00\x00\x64\x65\x6C\x75\x78\x00\x00\x00\x05\x00\x05\x00\x64\x01\x00\x00\x73\x5F\x64\x65" -"\x6C\x75\x78\x6D\x61\x70\x00\x00\x05\x00\x04\x00\x7B\x01\x00\x00\x73\x70\x65\x63\x73\x00\x00\x00\x05\x00\x05\x00\x7C\x01\x00\x00" -"\x73\x5F\x73\x70\x65\x63\x75\x6C\x61\x72\x00\x00\x05\x00\x04\x00\x82\x01\x00\x00\x68\x61\x6C\x66\x64\x69\x72\x00\x05\x00\x04\x00" -"\x93\x01\x00\x00\x73\x70\x65\x63\x00\x00\x00\x00\x05\x00\x03\x00\xAB\x01\x00\x00\x72\x74\x63\x00\x05\x00\x05\x00\xB5\x01\x00\x00" -"\x69\x6E\x76\x73\x75\x72\x66\x61\x63\x65\x00\x00\x05\x00\x06\x00\xD2\x01\x00\x00\x73\x5F\x72\x65\x66\x6C\x65\x63\x74\x6D\x61\x73" -"\x6B\x00\x00\x00\x05\x00\x06\x00\xDA\x01\x00\x00\x73\x5F\x72\x65\x66\x6C\x65\x63\x74\x63\x75\x62\x65\x00\x00\x00\x05\x00\x03\x00" -"\xEA\x01\x00\x00\x70\x61\x6C\x00\x05\x00\x05\x00\xEB\x01\x00\x00\x73\x5F\x70\x61\x6C\x65\x74\x74\x65\x64\x00\x00\x05\x00\x04\x00" -"\xF4\x01\x00\x00\x73\x5F\x74\x30\x00\x00\x00\x00\x05\x00\x05\x00\x18\x02\x00\x00\x5F\x46\x55\x4C\x4C\x42\x52\x49\x47\x48\x54\x00" -"\x05\x00\x06\x00\x1C\x02\x00\x00\x73\x5F\x66\x75\x6C\x6C\x62\x72\x69\x67\x68\x74\x00\x00\x00\x00\x05\x00\x05\x00\x2B\x02\x00\x00" -"\x61\x72\x67\x5F\x6D\x61\x73\x6B\x00\x00\x00\x00\x05\x00\x05\x00\x2F\x02\x00\x00\x5F\x61\x72\x67\x5F\x6D\x61\x73\x6B\x6C\x74\x00" -"\x05\x00\x04\x00\x41\x02\x00\x00\x70\x61\x72\x61\x6D\x00\x00\x00\x05\x00\x05\x00\x44\x02\x00\x00\x6C\x69\x67\x68\x74\x62\x6C\x6F" -"\x63\x6B\x00\x00\x06\x00\x07\x00\x44\x02\x00\x00\x00\x00\x00\x00\x6C\x5F\x63\x75\x62\x65\x6D\x61\x74\x72\x69\x78\x00\x00\x00\x00" -"\x06\x00\x07\x00\x44\x02\x00\x00\x01\x00\x00\x00\x6C\x5F\x6C\x69\x67\x68\x74\x70\x6F\x73\x69\x74\x69\x6F\x6E\x00\x06\x00\x05\x00" -"\x44\x02\x00\x00\x02\x00\x00\x00\x6C\x70\x61\x64\x31\x00\x00\x00\x06\x00\x07\x00\x44\x02\x00\x00\x03\x00\x00\x00\x6C\x5F\x6C\x69" -"\x67\x68\x74\x63\x6F\x6C\x6F\x75\x72\x00\x00\x00\x06\x00\x05\x00\x44\x02\x00\x00\x04\x00\x00\x00\x6C\x70\x61\x64\x32\x00\x00\x00" -"\x06\x00\x08\x00\x44\x02\x00\x00\x05\x00\x00\x00\x6C\x5F\x6C\x69\x67\x68\x74\x63\x6F\x6C\x6F\x75\x72\x73\x63\x61\x6C\x65\x00\x00" -"\x06\x00\x07\x00\x44\x02\x00\x00\x06\x00\x00\x00\x6C\x5F\x6C\x69\x67\x68\x74\x72\x61\x64\x69\x75\x73\x00\x00\x00\x06\x00\x07\x00" -"\x44\x02\x00\x00\x07\x00\x00\x00\x6C\x5F\x73\x68\x61\x64\x6F\x77\x6D\x61\x70\x70\x72\x6F\x6A\x00\x06\x00\x08\x00\x44\x02\x00\x00" -"\x08\x00\x00\x00\x6C\x5F\x73\x68\x61\x64\x6F\x77\x6D\x61\x70\x73\x63\x61\x6C\x65\x00\x00\x00\x00\x06\x00\x05\x00\x44\x02\x00\x00" -"\x09\x00\x00\x00\x6C\x70\x61\x64\x33\x00\x00\x00\x05\x00\x03\x00\x46\x02\x00\x00\x00\x00\x00\x00\x47\x00\x04\x00\x1F\x00\x00\x00" -"\x01\x00\x00\x00\x15\x00\x00\x00\x47\x00\x04\x00\x2D\x00\x00\x00\x06\x00\x00\x00\x10\x00\x00\x00\x48\x00\x04\x00\x2E\x00\x00\x00" -"\x00\x00\x00\x00\x05\x00\x00\x00\x48\x00\x05\x00\x2E\x00\x00\x00\x00\x00\x00\x00\x23\x00\x00\x00\x00\x00\x00\x00\x48\x00\x05\x00" -"\x2E\x00\x00\x00\x00\x00\x00\x00\x07\x00\x00\x00\x10\x00\x00\x00\x48\x00\x04\x00\x2E\x00\x00\x00\x01\x00\x00\x00\x05\x00\x00\x00" -"\x48\x00\x05\x00\x2E\x00\x00\x00\x01\x00\x00\x00\x23\x00\x00\x00\x40\x00\x00\x00\x48\x00\x05\x00\x2E\x00\x00\x00\x01\x00\x00\x00" -"\x07\x00\x00\x00\x10\x00\x00\x00\x48\x00\x04\x00\x2E\x00\x00\x00\x02\x00\x00\x00\x05\x00\x00\x00\x48\x00\x05\x00\x2E\x00\x00\x00" -"\x02\x00\x00\x00\x23\x00\x00\x00\x80\x00\x00\x00\x48\x00\x05\x00\x2E\x00\x00\x00\x02\x00\x00\x00\x07\x00\x00\x00\x10\x00\x00\x00" -"\x48\x00\x05\x00\x2E\x00\x00\x00\x03\x00\x00\x00\x23\x00\x00\x00\xC0\x00\x00\x00\x48\x00\x05\x00\x2E\x00\x00\x00\x04\x00\x00\x00" -"\x23\x00\x00\x00\xCC\x00\x00\x00\x48\x00\x05\x00\x2E\x00\x00\x00\x05\x00\x00\x00\x23\x00\x00\x00\xD0\x00\x00\x00\x48\x00\x05\x00" -"\x2E\x00\x00\x00\x06\x00\x00\x00\x23\x00\x00\x00\xDC\x00\x00\x00\x48\x00\x05\x00\x2E\x00\x00\x00\x07\x00\x00\x00\x23\x00\x00\x00" -"\xE0\x00\x00\x00\x48\x00\x05\x00\x2E\x00\x00\x00\x08\x00\x00\x00\x23\x00\x00\x00\xEC\x00\x00\x00\x48\x00\x05\x00\x2E\x00\x00\x00" -"\x09\x00\x00\x00\x23\x00\x00\x00\xF0\x00\x00\x00\x48\x00\x05\x00\x2E\x00\x00\x00\x0A\x00\x00\x00\x23\x00\x00\x00\xFC\x00\x00\x00" -"\x48\x00\x05\x00\x2E\x00\x00\x00\x0B\x00\x00\x00\x23\x00\x00\x00\x00\x01\x00\x00\x48\x00\x05\x00\x2E\x00\x00\x00\x0C\x00\x00\x00" -"\x23\x00\x00\x00\x40\x01\x00\x00\x48\x00\x05\x00\x2E\x00\x00\x00\x0D\x00\x00\x00\x23\x00\x00\x00\x4C\x01\x00\x00\x48\x00\x05\x00" -"\x2E\x00\x00\x00\x0E\x00\x00\x00\x23\x00\x00\x00\x50\x01\x00\x00\x48\x00\x05\x00\x2E\x00\x00\x00\x0F\x00\x00\x00\x23\x00\x00\x00" -"\x5C\x01\x00\x00\x48\x00\x05\x00\x2E\x00\x00\x00\x10\x00\x00\x00\x23\x00\x00\x00\x60\x01\x00\x00\x48\x00\x05\x00\x2E\x00\x00\x00" -"\x11\x00\x00\x00\x23\x00\x00\x00\x6C\x01\x00\x00\x48\x00\x05\x00\x2E\x00\x00\x00\x12\x00\x00\x00\x23\x00\x00\x00\x70\x01\x00\x00" -"\x48\x00\x05\x00\x2E\x00\x00\x00\x13\x00\x00\x00\x23\x00\x00\x00\x80\x01\x00\x00\x48\x00\x05\x00\x2E\x00\x00\x00\x14\x00\x00\x00" -"\x23\x00\x00\x00\x90\x01\x00\x00\x48\x00\x05\x00\x2E\x00\x00\x00\x15\x00\x00\x00\x23\x00\x00\x00\x94\x01\x00\x00\x48\x00\x05\x00" -"\x2E\x00\x00\x00\x16\x00\x00\x00\x23\x00\x00\x00\x98\x01\x00\x00\x47\x00\x03\x00\x2E\x00\x00\x00\x02\x00\x00\x00\x47\x00\x04\x00" -"\x30\x00\x00\x00\x22\x00\x00\x00\x00\x00\x00\x00\x47\x00\x04\x00\x30\x00\x00\x00\x21\x00\x00\x00\x00\x00\x00\x00\x47\x00\x04\x00" -"\x36\x00\x00\x00\x0B\x00\x00\x00\x0F\x00\x00\x00\x47\x00\x04\x00\x47\x00\x00\x00\x01\x00\x00\x00\x03\x01\x00\x00\x47\x00\x04\x00" -"\x83\x00\x00\x00\x01\x00\x00\x00\x01\x01\x00\x00\x47\x00\x04\x00\xD1\x00\x00\x00\x01\x00\x00\x00\x00\x01\x00\x00\x47\x00\x04\x00" -"\x03\x01\x00\x00\x1E\x00\x00\x00\x02\x00\x00\x00\x47\x00\x04\x00\x08\x01\x00\x00\x22\x00\x00\x00\x00\x00\x00\x00\x47\x00\x04\x00" -"\x08\x01\x00\x00\x21\x00\x00\x00\x03\x00\x00\x00\x47\x00\x04\x00\x0A\x01\x00\x00\x1E\x00\x00\x00\x01\x00\x00\x00\x47\x00\x04\x00" -"\x11\x01\x00\x00\x1E\x00\x00\x00\x00\x00\x00\x00\x47\x00\x04\x00\x12\x01\x00\x00\x22\x00\x00\x00\x00\x00\x00\x00\x47\x00\x04\x00" -"\x12\x01\x00\x00\x21\x00\x00\x00\x02\x00\x00\x00\x47\x00\x04\x00\x16\x01\x00\x00\x01\x00\x00\x00\x10\x00\x00\x00\x47\x00\x04\x00" -"\x1A\x01\x00\x00\x01\x00\x00\x00\x02\x01\x00\x00\x47\x00\x04\x00\x1D\x01\x00\x00\x01\x00\x00\x00\x13\x00\x00\x00\x47\x00\x04\x00" -"\x33\x01\x00\x00\x01\x00\x00\x00\x04\x01\x00\x00\x47\x00\x04\x00\x38\x01\x00\x00\x1E\x00\x00\x00\x03\x00\x00\x00\x47\x00\x04\x00" -"\x41\x01\x00\x00\x01\x00\x00\x00\x05\x01\x00\x00\x47\x00\x04\x00\x46\x01\x00\x00\x1E\x00\x00\x00\x00\x00\x00\x00\x47\x00\x04\x00" -"\x50\x01\x00\x00\x22\x00\x00\x00\x00\x00\x00\x00\x47\x00\x04\x00\x50\x01\x00\x00\x21\x00\x00\x00\x09\x00\x00\x00\x47\x00\x04\x00" -"\x64\x01\x00\x00\x22\x00\x00\x00\x00\x00\x00\x00\x47\x00\x04\x00\x64\x01\x00\x00\x21\x00\x00\x00\x0A\x00\x00\x00\x47\x00\x04\x00" -"\x7C\x01\x00\x00\x22\x00\x00\x00\x00\x00\x00\x00\x47\x00\x04\x00\x7C\x01\x00\x00\x21\x00\x00\x00\x04\x00\x00\x00\x47\x00\x04\x00" -"\xB5\x01\x00\x00\x1E\x00\x00\x00\x04\x00\x00\x00\x47\x00\x04\x00\xD2\x01\x00\x00\x22\x00\x00\x00\x00\x00\x00\x00\x47\x00\x04\x00" -"\xD2\x01\x00\x00\x21\x00\x00\x00\x08\x00\x00\x00\x47\x00\x04\x00\xDA\x01\x00\x00\x22\x00\x00\x00\x00\x00\x00\x00\x47\x00\x04\x00" -"\xDA\x01\x00\x00\x21\x00\x00\x00\x07\x00\x00\x00\x47\x00\x04\x00\xEB\x01\x00\x00\x22\x00\x00\x00\x00\x00\x00\x00\x47\x00\x04\x00" -"\xEB\x01\x00\x00\x21\x00\x00\x00\x06\x00\x00\x00\x47\x00\x04\x00\xF4\x01\x00\x00\x22\x00\x00\x00\x00\x00\x00\x00\x47\x00\x04\x00" -"\xF4\x01\x00\x00\x21\x00\x00\x00\x0B\x00\x00\x00\x47\x00\x04\x00\x18\x02\x00\x00\x01\x00\x00\x00\x11\x00\x00\x00\x47\x00\x04\x00" -"\x1C\x02\x00\x00\x22\x00\x00\x00\x00\x00\x00\x00\x47\x00\x04\x00\x1C\x02\x00\x00\x21\x00\x00\x00\x05\x00\x00\x00\x47\x00\x04\x00" -"\x2B\x02\x00\x00\x01\x00\x00\x00\x06\x01\x00\x00\x47\x00\x04\x00\x2F\x02\x00\x00\x01\x00\x00\x00\x07\x01\x00\x00\x48\x00\x04\x00" -"\x44\x02\x00\x00\x00\x00\x00\x00\x05\x00\x00\x00\x48\x00\x05\x00\x44\x02\x00\x00\x00\x00\x00\x00\x23\x00\x00\x00\x00\x00\x00\x00" -"\x48\x00\x05\x00\x44\x02\x00\x00\x00\x00\x00\x00\x07\x00\x00\x00\x10\x00\x00\x00\x48\x00\x05\x00\x44\x02\x00\x00\x01\x00\x00\x00" -"\x23\x00\x00\x00\x40\x00\x00\x00\x48\x00\x05\x00\x44\x02\x00\x00\x02\x00\x00\x00\x23\x00\x00\x00\x4C\x00\x00\x00\x48\x00\x05\x00" -"\x44\x02\x00\x00\x03\x00\x00\x00\x23\x00\x00\x00\x50\x00\x00\x00\x48\x00\x05\x00\x44\x02\x00\x00\x04\x00\x00\x00\x23\x00\x00\x00" -"\x5C\x00\x00\x00\x48\x00\x05\x00\x44\x02\x00\x00\x05\x00\x00\x00\x23\x00\x00\x00\x60\x00\x00\x00\x48\x00\x05\x00\x44\x02\x00\x00" -"\x06\x00\x00\x00\x23\x00\x00\x00\x6C\x00\x00\x00\x48\x00\x05\x00\x44\x02\x00\x00\x07\x00\x00\x00\x23\x00\x00\x00\x70\x00\x00\x00" -"\x48\x00\x05\x00\x44\x02\x00\x00\x08\x00\x00\x00\x23\x00\x00\x00\x80\x00\x00\x00\x48\x00\x05\x00\x44\x02\x00\x00\x09\x00\x00\x00" -"\x23\x00\x00\x00\x88\x00\x00\x00\x47\x00\x03\x00\x44\x02\x00\x00\x02\x00\x00\x00\x47\x00\x04\x00\x46\x02\x00\x00\x22\x00\x00\x00" -"\x00\x00\x00\x00\x47\x00\x04\x00\x46\x02\x00\x00\x21\x00\x00\x00\x01\x00\x00\x00\x13\x00\x02\x00\x02\x00\x00\x00\x21\x00\x03\x00" -"\x03\x00\x00\x00\x02\x00\x00\x00\x16\x00\x03\x00\x06\x00\x00\x00\x20\x00\x00\x00\x17\x00\x04\x00\x07\x00\x00\x00\x06\x00\x00\x00" -"\x03\x00\x00\x00\x20\x00\x04\x00\x08\x00\x00\x00\x07\x00\x00\x00\x07\x00\x00\x00\x21\x00\x04\x00\x09\x00\x00\x00\x07\x00\x00\x00" -"\x08\x00\x00\x00\x17\x00\x04\x00\x0D\x00\x00\x00\x06\x00\x00\x00\x04\x00\x00\x00\x20\x00\x04\x00\x0E\x00\x00\x00\x07\x00\x00\x00" -"\x0D\x00\x00\x00\x21\x00\x04\x00\x0F\x00\x00\x00\x0D\x00\x00\x00\x0E\x00\x00\x00\x19\x00\x09\x00\x13\x00\x00\x00\x06\x00\x00\x00" -"\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x1B\x00\x03\x00\x14\x00\x00\x00" -"\x13\x00\x00\x00\x20\x00\x04\x00\x15\x00\x00\x00\x00\x00\x00\x00\x14\x00\x00\x00\x17\x00\x04\x00\x16\x00\x00\x00\x06\x00\x00\x00" -"\x02\x00\x00\x00\x20\x00\x04\x00\x17\x00\x00\x00\x07\x00\x00\x00\x16\x00\x00\x00\x21\x00\x06\x00\x18\x00\x00\x00\x16\x00\x00\x00" -"\x15\x00\x00\x00\x17\x00\x00\x00\x08\x00\x00\x00\x15\x00\x04\x00\x1E\x00\x00\x00\x20\x00\x00\x00\x01\x00\x00\x00\x32\x00\x04\x00" -"\x1E\x00\x00\x00\x1F\x00\x00\x00\x15\x00\x00\x00\x2B\x00\x04\x00\x1E\x00\x00\x00\x20\x00\x00\x00\x00\x00\x00\x00\x14\x00\x02\x00" -"\x21\x00\x00\x00\x34\x00\x06\x00\x21\x00\x00\x00\x22\x00\x00\x00\xAB\x00\x00\x00\x1F\x00\x00\x00\x20\x00\x00\x00\x34\x00\x05\x00" -"\x21\x00\x00\x00\x23\x00\x00\x00\xA8\x00\x00\x00\x22\x00\x00\x00\x20\x00\x04\x00\x28\x00\x00\x00\x07\x00\x00\x00\x06\x00\x00\x00" -"\x18\x00\x04\x00\x2A\x00\x00\x00\x0D\x00\x00\x00\x04\x00\x00\x00\x15\x00\x04\x00\x2B\x00\x00\x00\x20\x00\x00\x00\x00\x00\x00\x00" -"\x2B\x00\x04\x00\x2B\x00\x00\x00\x2C\x00\x00\x00\x04\x00\x00\x00\x1C\x00\x04\x00\x2D\x00\x00\x00\x0D\x00\x00\x00\x2C\x00\x00\x00" -"\x1E\x00\x19\x00\x2E\x00\x00\x00\x2A\x00\x00\x00\x2A\x00\x00\x00\x2A\x00\x00\x00\x07\x00\x00\x00\x06\x00\x00\x00\x07\x00\x00\x00" -"\x06\x00\x00\x00\x07\x00\x00\x00\x06\x00\x00\x00\x07\x00\x00\x00\x06\x00\x00\x00\x2D\x00\x00\x00\x07\x00\x00\x00\x06\x00\x00\x00" -"\x07\x00\x00\x00\x06\x00\x00\x00\x07\x00\x00\x00\x06\x00\x00\x00\x0D\x00\x00\x00\x0D\x00\x00\x00\x06\x00\x00\x00\x06\x00\x00\x00" -"\x16\x00\x00\x00\x20\x00\x04\x00\x2F\x00\x00\x00\x02\x00\x00\x00\x2E\x00\x00\x00\x3B\x00\x04\x00\x2F\x00\x00\x00\x30\x00\x00\x00" -"\x02\x00\x00\x00\x2B\x00\x04\x00\x1E\x00\x00\x00\x31\x00\x00\x00\x14\x00\x00\x00\x20\x00\x04\x00\x32\x00\x00\x00\x02\x00\x00\x00" -"\x06\x00\x00\x00\x20\x00\x04\x00\x35\x00\x00\x00\x01\x00\x00\x00\x0D\x00\x00\x00\x3B\x00\x04\x00\x35\x00\x00\x00\x36\x00\x00\x00" -"\x01\x00\x00\x00\x2B\x00\x04\x00\x2B\x00\x00\x00\x37\x00\x00\x00\x02\x00\x00\x00\x20\x00\x04\x00\x38\x00\x00\x00\x01\x00\x00\x00" -"\x06\x00\x00\x00\x2B\x00\x04\x00\x2B\x00\x00\x00\x3C\x00\x00\x00\x03\x00\x00\x00\x2B\x00\x04\x00\x06\x00\x00\x00\x40\x00\x00\x00" -"\x00\x00\x00\x00\x2B\x00\x04\x00\x1E\x00\x00\x00\x42\x00\x00\x00\x15\x00\x00\x00\x32\x00\x04\x00\x1E\x00\x00\x00\x47\x00\x00\x00" -"\x03\x01\x00\x00\x34\x00\x06\x00\x21\x00\x00\x00\x48\x00\x00\x00\xAB\x00\x00\x00\x47\x00\x00\x00\x20\x00\x00\x00\x2B\x00\x04\x00" -"\x06\x00\x00\x00\x50\x00\x00\x00\x3B\xAA\xB8\x3F\x2B\x00\x04\x00\x06\x00\x00\x00\x54\x00\x00\x00\x00\x00\x80\x3F\x2B\x00\x04\x00" -"\x1E\x00\x00\x00\x55\x00\x00\x00\x13\x00\x00\x00\x20\x00\x04\x00\x5F\x00\x00\x00\x02\x00\x00\x00\x0D\x00\x00\x00\x34\x00\x06\x00" -"\x21\x00\x00\x00\x69\x00\x00\x00\xAB\x00\x00\x00\x1F\x00\x00\x00\x20\x00\x00\x00\x34\x00\x05\x00\x21\x00\x00\x00\x6A\x00\x00\x00" -"\xA8\x00\x00\x00\x69\x00\x00\x00\x2A\x00\x03\x00\x21\x00\x00\x00\x7C\x00\x00\x00\x32\x00\x04\x00\x06\x00\x00\x00\x83\x00\x00\x00" -"\x00\x80\x80\x43\x2B\x00\x04\x00\x06\x00\x00\x00\x86\x00\x00\x00\x00\x00\x80\xBF\x2C\x00\x05\x00\x16\x00\x00\x00\x87\x00\x00\x00" -"\x86\x00\x00\x00\x54\x00\x00\x00\x2B\x00\x04\x00\x06\x00\x00\x00\x94\x00\x00\x00\x00\x00\x20\x41\x2B\x00\x04\x00\x06\x00\x00\x00" -"\xB5\x00\x00\x00\x00\x00\xA0\x40\x2B\x00\x04\x00\x06\x00\x00\x00\xC2\x00\x00\x00\x00\x00\x00\x3F\x32\x00\x04\x00\x06\x00\x00\x00" -"\xD1\x00\x00\x00\x00\x00\x80\x43\x2B\x00\x04\x00\x06\x00\x00\x00\xE1\x00\x00\x00\xFA\x7E\xAA\x3E\x20\x00\x04\x00\x02\x01\x00\x00" -"\x01\x00\x00\x00\x16\x00\x00\x00\x3B\x00\x04\x00\x02\x01\x00\x00\x03\x01\x00\x00\x01\x00\x00\x00\x3B\x00\x04\x00\x15\x00\x00\x00" -"\x08\x01\x00\x00\x00\x00\x00\x00\x20\x00\x04\x00\x09\x01\x00\x00\x01\x00\x00\x00\x07\x00\x00\x00\x3B\x00\x04\x00\x09\x01\x00\x00" -"\x0A\x01\x00\x00\x01\x00\x00\x00\x20\x00\x04\x00\x10\x01\x00\x00\x03\x00\x00\x00\x0D\x00\x00\x00\x3B\x00\x04\x00\x10\x01\x00\x00" -"\x11\x01\x00\x00\x03\x00\x00\x00\x3B\x00\x04\x00\x15\x00\x00\x00\x12\x01\x00\x00\x00\x00\x00\x00\x32\x00\x04\x00\x1E\x00\x00\x00" -"\x16\x01\x00\x00\x10\x00\x00\x00\x34\x00\x06\x00\x21\x00\x00\x00\x17\x01\x00\x00\xAB\x00\x00\x00\x16\x01\x00\x00\x20\x00\x00\x00" -"\x32\x00\x04\x00\x06\x00\x00\x00\x1A\x01\x00\x00\x00\x00\x81\x43\x32\x00\x04\x00\x1E\x00\x00\x00\x1D\x01\x00\x00\x13\x00\x00\x00" -"\x34\x00\x06\x00\x21\x00\x00\x00\x1E\x01\x00\x00\xAB\x00\x00\x00\x1D\x01\x00\x00\x20\x00\x00\x00\x34\x00\x06\x00\x21\x00\x00\x00" -"\x2E\x01\x00\x00\xAB\x00\x00\x00\x1D\x01\x00\x00\x20\x00\x00\x00\x2C\x00\x06\x00\x07\x00\x00\x00\x32\x01\x00\x00\x40\x00\x00\x00" -"\x40\x00\x00\x00\x54\x00\x00\x00\x32\x00\x04\x00\x1E\x00\x00\x00\x33\x01\x00\x00\x04\x01\x00\x00\x34\x00\x06\x00\x21\x00\x00\x00" -"\x34\x01\x00\x00\xAB\x00\x00\x00\x33\x01\x00\x00\x20\x00\x00\x00\x3B\x00\x04\x00\x35\x00\x00\x00\x38\x01\x00\x00\x01\x00\x00\x00" -"\x2B\x00\x04\x00\x1E\x00\x00\x00\x3B\x01\x00\x00\x0B\x00\x00\x00\x32\x00\x04\x00\x1E\x00\x00\x00\x41\x01\x00\x00\x05\x01\x00\x00" -"\x34\x00\x06\x00\x21\x00\x00\x00\x42\x01\x00\x00\xAB\x00\x00\x00\x41\x01\x00\x00\x20\x00\x00\x00\x3B\x00\x04\x00\x02\x01\x00\x00" -"\x46\x01\x00\x00\x01\x00\x00\x00\x2B\x00\x04\x00\x06\x00\x00\x00\x48\x01\x00\x00\x00\x00\x80\x43\x2B\x00\x04\x00\x06\x00\x00\x00" -"\x4A\x01\x00\x00\x00\x00\x00\x41\x2B\x00\x04\x00\x06\x00\x00\x00\x4D\x01\x00\x00\x00\x00\x00\x45\x3B\x00\x04\x00\x15\x00\x00\x00" -"\x50\x01\x00\x00\x00\x00\x00\x00\x2B\x00\x04\x00\x06\x00\x00\x00\x63\x01\x00\x00\x00\x00\x00\x40\x3B\x00\x04\x00\x15\x00\x00\x00" -"\x64\x01\x00\x00\x00\x00\x00\x00\x2B\x00\x04\x00\x06\x00\x00\x00\x6C\x01\x00\x00\x00\x00\x80\x3E\x3B\x00\x04\x00\x15\x00\x00\x00" -"\x7C\x01\x00\x00\x00\x00\x00\x00\x2B\x00\x04\x00\x06\x00\x00\x00\x98\x01\x00\x00\x00\x00\x00\x42\x34\x00\x06\x00\x21\x00\x00\x00" -"\xA8\x01\x00\x00\xAB\x00\x00\x00\x1D\x01\x00\x00\x20\x00\x00\x00\x2B\x00\x04\x00\x2B\x00\x00\x00\xB0\x01\x00\x00\x00\x00\x00\x00" -"\x18\x00\x04\x00\xB3\x01\x00\x00\x07\x00\x00\x00\x03\x00\x00\x00\x20\x00\x04\x00\xB4\x01\x00\x00\x01\x00\x00\x00\xB3\x01\x00\x00" -"\x3B\x00\x04\x00\xB4\x01\x00\x00\xB5\x01\x00\x00\x01\x00\x00\x00\x2B\x00\x04\x00\x2B\x00\x00\x00\xB9\x01\x00\x00\x01\x00\x00\x00" -"\x2B\x00\x04\x00\x1E\x00\x00\x00\xBC\x01\x00\x00\x01\x00\x00\x00\x2B\x00\x04\x00\x1E\x00\x00\x00\xC3\x01\x00\x00\x02\x00\x00\x00" -"\x20\x00\x04\x00\xC8\x01\x00\x00\x02\x00\x00\x00\x2A\x00\x00\x00\x3B\x00\x04\x00\x15\x00\x00\x00\xD2\x01\x00\x00\x00\x00\x00\x00" -"\x19\x00\x09\x00\xD7\x01\x00\x00\x06\x00\x00\x00\x03\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00" -"\x00\x00\x00\x00\x1B\x00\x03\x00\xD8\x01\x00\x00\xD7\x01\x00\x00\x20\x00\x04\x00\xD9\x01\x00\x00\x00\x00\x00\x00\xD8\x01\x00\x00" -"\x3B\x00\x04\x00\xD9\x01\x00\x00\xDA\x01\x00\x00\x00\x00\x00\x00\x34\x00\x06\x00\x21\x00\x00\x00\xE5\x01\x00\x00\xAB\x00\x00\x00" -"\x41\x01\x00\x00\x20\x00\x00\x00\x3B\x00\x04\x00\x15\x00\x00\x00\xEB\x01\x00\x00\x00\x00\x00\x00\x2B\x00\x04\x00\x06\x00\x00\x00" -"\xF0\x01\x00\x00\x00\x00\x00\x3C\x3B\x00\x04\x00\x15\x00\x00\x00\xF4\x01\x00\x00\x00\x00\x00\x00\x20\x00\x04\x00\xFD\x01\x00\x00" -"\x03\x00\x00\x00\x06\x00\x00\x00\x32\x00\x04\x00\x1E\x00\x00\x00\x18\x02\x00\x00\x11\x00\x00\x00\x34\x00\x06\x00\x21\x00\x00\x00" -"\x19\x02\x00\x00\xAB\x00\x00\x00\x18\x02\x00\x00\x20\x00\x00\x00\x3B\x00\x04\x00\x15\x00\x00\x00\x1C\x02\x00\x00\x00\x00\x00\x00" -"\x2B\x00\x04\x00\x1E\x00\x00\x00\x27\x02\x00\x00\x12\x00\x00\x00\x32\x00\x04\x00\x06\x00\x00\x00\x2B\x02\x00\x00\x00\x00\x83\x43" -"\x32\x00\x04\x00\x1E\x00\x00\x00\x2F\x02\x00\x00\x07\x01\x00\x00\x34\x00\x06\x00\x21\x00\x00\x00\x30\x02\x00\x00\xAB\x00\x00\x00" -"\x2F\x02\x00\x00\x20\x00\x00\x00\x1E\x00\x0C\x00\x44\x02\x00\x00\x2A\x00\x00\x00\x07\x00\x00\x00\x06\x00\x00\x00\x07\x00\x00\x00" -"\x06\x00\x00\x00\x07\x00\x00\x00\x06\x00\x00\x00\x0D\x00\x00\x00\x16\x00\x00\x00\x16\x00\x00\x00\x20\x00\x04\x00\x45\x02\x00\x00" -"\x02\x00\x00\x00\x44\x02\x00\x00\x3B\x00\x04\x00\x45\x02\x00\x00\x46\x02\x00\x00\x02\x00\x00\x00\x36\x00\x05\x00\x02\x00\x00\x00" -"\x04\x00\x00\x00\x00\x00\x00\x00\x03\x00\x00\x00\xF8\x00\x02\x00\x05\x00\x00\x00\x3B\x00\x04\x00\x17\x00\x00\x00\x01\x01\x00\x00" -"\x07\x00\x00\x00\x3B\x00\x04\x00\x17\x00\x00\x00\x0B\x01\x00\x00\x07\x00\x00\x00\x3B\x00\x04\x00\x08\x00\x00\x00\x0D\x01\x00\x00" -"\x07\x00\x00\x00\x3B\x00\x04\x00\x08\x00\x00\x00\x23\x01\x00\x00\x07\x00\x00\x00\x3B\x00\x04\x00\x08\x00\x00\x00\x37\x01\x00\x00" -"\x07\x00\x00\x00\x3B\x00\x04\x00\x17\x00\x00\x00\x45\x01\x00\x00\x07\x00\x00\x00\x3B\x00\x04\x00\x08\x00\x00\x00\x62\x01\x00\x00" -"\x07\x00\x00\x00\x3B\x00\x04\x00\x0E\x00\x00\x00\x7B\x01\x00\x00\x07\x00\x00\x00\x3B\x00\x04\x00\x08\x00\x00\x00\x82\x01\x00\x00" -"\x07\x00\x00\x00\x3B\x00\x04\x00\x28\x00\x00\x00\x93\x01\x00\x00\x07\x00\x00\x00\x3B\x00\x04\x00\x08\x00\x00\x00\xAB\x01\x00\x00" -"\x07\x00\x00\x00\x3B\x00\x04\x00\x28\x00\x00\x00\xEA\x01\x00\x00\x07\x00\x00\x00\x3B\x00\x04\x00\x0E\x00\x00\x00\x41\x02\x00\x00" -"\x07\x00\x00\x00\x3D\x00\x04\x00\x16\x00\x00\x00\x04\x01\x00\x00\x03\x01\x00\x00\x3E\x00\x03\x00\x01\x01\x00\x00\x04\x01\x00\x00" -"\xBA\x00\x05\x00\x21\x00\x00\x00\x05\x01\x00\x00\xD1\x00\x00\x00\x40\x00\x00\x00\xF7\x00\x03\x00\x07\x01\x00\x00\x00\x00\x00\x00" -"\xFA\x00\x04\x00\x05\x01\x00\x00\x06\x01\x00\x00\x07\x01\x00\x00\xF8\x00\x02\x00\x06\x01\x00\x00\x3D\x00\x04\x00\x16\x00\x00\x00" -"\x0C\x01\x00\x00\x01\x01\x00\x00\x3E\x00\x03\x00\x0B\x01\x00\x00\x0C\x01\x00\x00\x3D\x00\x04\x00\x07\x00\x00\x00\x0E\x01\x00\x00" -"\x0A\x01\x00\x00\x3E\x00\x03\x00\x0D\x01\x00\x00\x0E\x01\x00\x00\x39\x00\x07\x00\x16\x00\x00\x00\x0F\x01\x00\x00\x1C\x00\x00\x00" -"\x08\x01\x00\x00\x0B\x01\x00\x00\x0D\x01\x00\x00\x3E\x00\x03\x00\x01\x01\x00\x00\x0F\x01\x00\x00\xF9\x00\x02\x00\x07\x01\x00\x00" -"\xF8\x00\x02\x00\x07\x01\x00\x00\x3D\x00\x04\x00\x14\x00\x00\x00\x13\x01\x00\x00\x12\x01\x00\x00\x3D\x00\x04\x00\x16\x00\x00\x00" -"\x14\x01\x00\x00\x01\x01\x00\x00\x57\x00\x05\x00\x0D\x00\x00\x00\x15\x01\x00\x00\x13\x01\x00\x00\x14\x01\x00\x00\x3E\x00\x03\x00" -"\x11\x01\x00\x00\x15\x01\x00\x00\xF7\x00\x03\x00\x19\x01\x00\x00\x00\x00\x00\x00\xFA\x00\x04\x00\x17\x01\x00\x00\x18\x01\x00\x00" -"\x19\x01\x00\x00\xF8\x00\x02\x00\x18\x01\x00\x00\xBA\x00\x05\x00\x21\x00\x00\x00\x1B\x01\x00\x00\x1A\x01\x00\x00\x40\x00\x00\x00" -"\xA6\x00\x05\x00\x21\x00\x00\x00\x1C\x01\x00\x00\x7C\x00\x00\x00\x1B\x01\x00\x00\xA6\x00\x05\x00\x21\x00\x00\x00\x1F\x01\x00\x00" -"\x1C\x01\x00\x00\x1E\x01\x00\x00\xF9\x00\x02\x00\x19\x01\x00\x00\xF8\x00\x02\x00\x19\x01\x00\x00\xF5\x00\x07\x00\x21\x00\x00\x00" -"\x20\x01\x00\x00\x17\x01\x00\x00\x07\x01\x00\x00\x1F\x01\x00\x00\x18\x01\x00\x00\xF7\x00\x03\x00\x22\x01\x00\x00\x00\x00\x00\x00" -"\xFA\x00\x04\x00\x20\x01\x00\x00\x21\x01\x00\x00\x2B\x01\x00\x00\xF8\x00\x02\x00\x21\x01\x00\x00\x3D\x00\x04\x00\x14\x00\x00\x00" -"\x24\x01\x00\x00\x08\x01\x00\x00\x3D\x00\x04\x00\x16\x00\x00\x00\x25\x01\x00\x00\x01\x01\x00\x00\x57\x00\x05\x00\x0D\x00\x00\x00" -"\x26\x01\x00\x00\x24\x01\x00\x00\x25\x01\x00\x00\x4F\x00\x08\x00\x07\x00\x00\x00\x27\x01\x00\x00\x26\x01\x00\x00\x26\x01\x00\x00" -"\x00\x00\x00\x00\x01\x00\x00\x00\x02\x00\x00\x00\x50\x00\x06\x00\x07\x00\x00\x00\x28\x01\x00\x00\xC2\x00\x00\x00\xC2\x00\x00\x00" -"\xC2\x00\x00\x00\x83\x00\x05\x00\x07\x00\x00\x00\x29\x01\x00\x00\x27\x01\x00\x00\x28\x01\x00\x00\x0C\x00\x06\x00\x07\x00\x00\x00" -"\x2A\x01\x00\x00\x01\x00\x00\x00\x45\x00\x00\x00\x29\x01\x00\x00\x3E\x00\x03\x00\x23\x01\x00\x00\x2A\x01\x00\x00\xF9\x00\x02\x00" -"\x22\x01\x00\x00\xF8\x00\x02\x00\x2B\x01\x00\x00\xBA\x00\x05\x00\x21\x00\x00\x00\x2C\x01\x00\x00\x1A\x01\x00\x00\x40\x00\x00\x00" -"\xA6\x00\x05\x00\x21\x00\x00\x00\x2D\x01\x00\x00\x2C\x01\x00\x00\x7C\x00\x00\x00\xA6\x00\x05\x00\x21\x00\x00\x00\x2F\x01\x00\x00" -"\x2D\x01\x00\x00\x2E\x01\x00\x00\xF7\x00\x03\x00\x31\x01\x00\x00\x00\x00\x00\x00\xFA\x00\x04\x00\x2F\x01\x00\x00\x30\x01\x00\x00" -"\x31\x01\x00\x00\xF8\x00\x02\x00\x30\x01\x00\x00\x3E\x00\x03\x00\x23\x01\x00\x00\x32\x01\x00\x00\xF9\x00\x02\x00\x31\x01\x00\x00" -"\xF8\x00\x02\x00\x31\x01\x00\x00\xF9\x00\x02\x00\x22\x01\x00\x00\xF8\x00\x02\x00\x22\x01\x00\x00\xF7\x00\x03\x00\x36\x01\x00\x00" -"\x00\x00\x00\x00\xFA\x00\x04\x00\x34\x01\x00\x00\x35\x01\x00\x00\x40\x01\x00\x00\xF8\x00\x02\x00\x35\x01\x00\x00\x3D\x00\x04\x00" -"\x0D\x00\x00\x00\x39\x01\x00\x00\x38\x01\x00\x00\x4F\x00\x08\x00\x07\x00\x00\x00\x3A\x01\x00\x00\x39\x01\x00\x00\x39\x01\x00\x00" -"\x00\x00\x00\x00\x01\x00\x00\x00\x02\x00\x00\x00\x41\x00\x06\x00\x5F\x00\x00\x00\x3C\x01\x00\x00\x30\x00\x00\x00\x3B\x01\x00\x00" -"\x20\x00\x00\x00\x3D\x00\x04\x00\x0D\x00\x00\x00\x3D\x01\x00\x00\x3C\x01\x00\x00\x4F\x00\x08\x00\x07\x00\x00\x00\x3E\x01\x00\x00" -"\x3D\x01\x00\x00\x3D\x01\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x02\x00\x00\x00\x85\x00\x05\x00\x07\x00\x00\x00\x3F\x01\x00\x00" -"\x3A\x01\x00\x00\x3E\x01\x00\x00\x3E\x00\x03\x00\x37\x01\x00\x00\x3F\x01\x00\x00\xF9\x00\x02\x00\x36\x01\x00\x00\xF8\x00\x02\x00" -"\x40\x01\x00\x00\xF7\x00\x03\x00\x44\x01\x00\x00\x00\x00\x00\x00\xFA\x00\x04\x00\x42\x01\x00\x00\x43\x01\x00\x00\x58\x01\x00\x00" -"\xF8\x00\x02\x00\x43\x01\x00\x00\x3D\x00\x04\x00\x16\x00\x00\x00\x47\x01\x00\x00\x46\x01\x00\x00\x8E\x00\x05\x00\x16\x00\x00\x00" -"\x49\x01\x00\x00\x47\x01\x00\x00\x48\x01\x00\x00\x8E\x00\x05\x00\x16\x00\x00\x00\x4B\x01\x00\x00\x49\x01\x00\x00\x4A\x01\x00\x00" -"\x0C\x00\x06\x00\x16\x00\x00\x00\x4C\x01\x00\x00\x01\x00\x00\x00\x08\x00\x00\x00\x4B\x01\x00\x00\x50\x00\x05\x00\x16\x00\x00\x00" -"\x4E\x01\x00\x00\x4D\x01\x00\x00\x4D\x01\x00\x00\x88\x00\x05\x00\x16\x00\x00\x00\x4F\x01\x00\x00\x4C\x01\x00\x00\x4E\x01\x00\x00" -"\x3E\x00\x03\x00\x45\x01\x00\x00\x4F\x01\x00\x00\x3D\x00\x04\x00\x14\x00\x00\x00\x51\x01\x00\x00\x50\x01\x00\x00\x3D\x00\x04\x00" -"\x16\x00\x00\x00\x52\x01\x00\x00\x45\x01\x00\x00\x57\x00\x05\x00\x0D\x00\x00\x00\x53\x01\x00\x00\x51\x01\x00\x00\x52\x01\x00\x00" -"\x41\x00\x06\x00\x5F\x00\x00\x00\x54\x01\x00\x00\x30\x00\x00\x00\x3B\x01\x00\x00\x20\x00\x00\x00\x3D\x00\x04\x00\x0D\x00\x00\x00" -"\x55\x01\x00\x00\x54\x01\x00\x00\x85\x00\x05\x00\x0D\x00\x00\x00\x56\x01\x00\x00\x53\x01\x00\x00\x55\x01\x00\x00\x4F\x00\x08\x00" -"\x07\x00\x00\x00\x57\x01\x00\x00\x56\x01\x00\x00\x56\x01\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x02\x00\x00\x00\x3E\x00\x03\x00" -"\x37\x01\x00\x00\x57\x01\x00\x00\xF9\x00\x02\x00\x44\x01\x00\x00\xF8\x00\x02\x00\x58\x01\x00\x00\x3D\x00\x04\x00\x14\x00\x00\x00" -"\x59\x01\x00\x00\x50\x01\x00\x00\x3D\x00\x04\x00\x16\x00\x00\x00\x5A\x01\x00\x00\x46\x01\x00\x00\x57\x00\x05\x00\x0D\x00\x00\x00" -"\x5B\x01\x00\x00\x59\x01\x00\x00\x5A\x01\x00\x00\x41\x00\x06\x00\x5F\x00\x00\x00\x5C\x01\x00\x00\x30\x00\x00\x00\x3B\x01\x00\x00" -"\x20\x00\x00\x00\x3D\x00\x04\x00\x0D\x00\x00\x00\x5D\x01\x00\x00\x5C\x01\x00\x00\x85\x00\x05\x00\x0D\x00\x00\x00\x5E\x01\x00\x00" -"\x5B\x01\x00\x00\x5D\x01\x00\x00\x4F\x00\x08\x00\x07\x00\x00\x00\x5F\x01\x00\x00\x5E\x01\x00\x00\x5E\x01\x00\x00\x00\x00\x00\x00" -"\x01\x00\x00\x00\x02\x00\x00\x00\x3E\x00\x03\x00\x37\x01\x00\x00\x5F\x01\x00\x00\xF9\x00\x02\x00\x44\x01\x00\x00\xF8\x00\x02\x00" -"\x44\x01\x00\x00\xF7\x00\x03\x00\x61\x01\x00\x00\x00\x00\x00\x00\xFA\x00\x04\x00\x7C\x00\x00\x00\x60\x01\x00\x00\x61\x01\x00\x00" -"\xF8\x00\x02\x00\x60\x01\x00\x00\x3D\x00\x04\x00\x14\x00\x00\x00\x65\x01\x00\x00\x64\x01\x00\x00\x3D\x00\x04\x00\x16\x00\x00\x00" -"\x66\x01\x00\x00\x46\x01\x00\x00\x57\x00\x05\x00\x0D\x00\x00\x00\x67\x01\x00\x00\x65\x01\x00\x00\x66\x01\x00\x00\x4F\x00\x08\x00" -"\x07\x00\x00\x00\x68\x01\x00\x00\x67\x01\x00\x00\x67\x01\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x02\x00\x00\x00\x50\x00\x06\x00" -"\x07\x00\x00\x00\x69\x01\x00\x00\xC2\x00\x00\x00\xC2\x00\x00\x00\xC2\x00\x00\x00\x83\x00\x05\x00\x07\x00\x00\x00\x6A\x01\x00\x00" -"\x68\x01\x00\x00\x69\x01\x00\x00\x8E\x00\x05\x00\x07\x00\x00\x00\x6B\x01\x00\x00\x6A\x01\x00\x00\x63\x01\x00\x00\x3E\x00\x03\x00" -"\x62\x01\x00\x00\x6B\x01\x00\x00\x41\x00\x05\x00\x28\x00\x00\x00\x6D\x01\x00\x00\x62\x01\x00\x00\x37\x00\x00\x00\x3D\x00\x04\x00" -"\x06\x00\x00\x00\x6E\x01\x00\x00\x6D\x01\x00\x00\x0C\x00\x07\x00\x06\x00\x00\x00\x6F\x01\x00\x00\x01\x00\x00\x00\x28\x00\x00\x00" -"\x6C\x01\x00\x00\x6E\x01\x00\x00\x88\x00\x05\x00\x06\x00\x00\x00\x70\x01\x00\x00\x54\x00\x00\x00\x6F\x01\x00\x00\x3D\x00\x04\x00" -"\x07\x00\x00\x00\x71\x01\x00\x00\x37\x01\x00\x00\x8E\x00\x05\x00\x07\x00\x00\x00\x72\x01\x00\x00\x71\x01\x00\x00\x70\x01\x00\x00" -"\x3E\x00\x03\x00\x37\x01\x00\x00\x72\x01\x00\x00\x3D\x00\x04\x00\x07\x00\x00\x00\x73\x01\x00\x00\x23\x01\x00\x00\x3D\x00\x04\x00" -"\x07\x00\x00\x00\x74\x01\x00\x00\x62\x01\x00\x00\x94\x00\x05\x00\x06\x00\x00\x00\x75\x01\x00\x00\x73\x01\x00\x00\x74\x01\x00\x00" -"\x3D\x00\x04\x00\x07\x00\x00\x00\x76\x01\x00\x00\x37\x01\x00\x00\x8E\x00\x05\x00\x07\x00\x00\x00\x77\x01\x00\x00\x76\x01\x00\x00" -"\x75\x01\x00\x00\x3E\x00\x03\x00\x37\x01\x00\x00\x77\x01\x00\x00\xF9\x00\x02\x00\x61\x01\x00\x00\xF8\x00\x02\x00\x61\x01\x00\x00" -"\xF9\x00\x02\x00\x36\x01\x00\x00\xF8\x00\x02\x00\x36\x01\x00\x00\xBA\x00\x05\x00\x21\x00\x00\x00\x78\x01\x00\x00\x1A\x01\x00\x00" -"\x40\x00\x00\x00\xF7\x00\x03\x00\x7A\x01\x00\x00\x00\x00\x00\x00\xFA\x00\x04\x00\x78\x01\x00\x00\x79\x01\x00\x00\x7A\x01\x00\x00" -"\xF8\x00\x02\x00\x79\x01\x00\x00\x3D\x00\x04\x00\x14\x00\x00\x00\x7D\x01\x00\x00\x7C\x01\x00\x00\x3D\x00\x04\x00\x16\x00\x00\x00" -"\x7E\x01\x00\x00\x01\x01\x00\x00\x57\x00\x05\x00\x0D\x00\x00\x00\x7F\x01\x00\x00\x7D\x01\x00\x00\x7E\x01\x00\x00\x3E\x00\x03\x00" -"\x7B\x01\x00\x00\x7F\x01\x00\x00\xF7\x00\x03\x00\x81\x01\x00\x00\x00\x00\x00\x00\xFA\x00\x04\x00\x7C\x00\x00\x00\x80\x01\x00\x00" -"\x8E\x01\x00\x00\xF8\x00\x02\x00\x80\x01\x00\x00\x3D\x00\x04\x00\x07\x00\x00\x00\x83\x01\x00\x00\x0A\x01\x00\x00\x0C\x00\x06\x00" -"\x07\x00\x00\x00\x84\x01\x00\x00\x01\x00\x00\x00\x45\x00\x00\x00\x83\x01\x00\x00\x3D\x00\x04\x00\x14\x00\x00\x00\x85\x01\x00\x00" -"\x64\x01\x00\x00\x3D\x00\x04\x00\x16\x00\x00\x00\x86\x01\x00\x00\x46\x01\x00\x00\x57\x00\x05\x00\x0D\x00\x00\x00\x87\x01\x00\x00" -"\x85\x01\x00\x00\x86\x01\x00\x00\x4F\x00\x08\x00\x07\x00\x00\x00\x88\x01\x00\x00\x87\x01\x00\x00\x87\x01\x00\x00\x00\x00\x00\x00" -"\x01\x00\x00\x00\x02\x00\x00\x00\x50\x00\x06\x00\x07\x00\x00\x00\x89\x01\x00\x00\xC2\x00\x00\x00\xC2\x00\x00\x00\xC2\x00\x00\x00" -"\x83\x00\x05\x00\x07\x00\x00\x00\x8A\x01\x00\x00\x88\x01\x00\x00\x89\x01\x00\x00\x8E\x00\x05\x00\x07\x00\x00\x00\x8B\x01\x00\x00" -"\x8A\x01\x00\x00\x63\x01\x00\x00\x81\x00\x05\x00\x07\x00\x00\x00\x8C\x01\x00\x00\x84\x01\x00\x00\x8B\x01\x00\x00\x0C\x00\x06\x00" -"\x07\x00\x00\x00\x8D\x01\x00\x00\x01\x00\x00\x00\x45\x00\x00\x00\x8C\x01\x00\x00\x3E\x00\x03\x00\x82\x01\x00\x00\x8D\x01\x00\x00" -"\xF9\x00\x02\x00\x81\x01\x00\x00\xF8\x00\x02\x00\x8E\x01\x00\x00\x3D\x00\x04\x00\x07\x00\x00\x00\x8F\x01\x00\x00\x0A\x01\x00\x00" -"\x0C\x00\x06\x00\x07\x00\x00\x00\x90\x01\x00\x00\x01\x00\x00\x00\x45\x00\x00\x00\x8F\x01\x00\x00\x81\x00\x05\x00\x07\x00\x00\x00" -"\x91\x01\x00\x00\x90\x01\x00\x00\x32\x01\x00\x00\x0C\x00\x06\x00\x07\x00\x00\x00\x92\x01\x00\x00\x01\x00\x00\x00\x45\x00\x00\x00" -"\x91\x01\x00\x00\x3E\x00\x03\x00\x82\x01\x00\x00\x92\x01\x00\x00\xF9\x00\x02\x00\x81\x01\x00\x00\xF8\x00\x02\x00\x81\x01\x00\x00" -"\x3D\x00\x04\x00\x07\x00\x00\x00\x94\x01\x00\x00\x82\x01\x00\x00\x3D\x00\x04\x00\x07\x00\x00\x00\x95\x01\x00\x00\x23\x01\x00\x00" -"\x94\x00\x05\x00\x06\x00\x00\x00\x96\x01\x00\x00\x94\x01\x00\x00\x95\x01\x00\x00\x0C\x00\x07\x00\x06\x00\x00\x00\x97\x01\x00\x00" -"\x01\x00\x00\x00\x28\x00\x00\x00\x96\x01\x00\x00\x40\x00\x00\x00\x41\x00\x05\x00\x28\x00\x00\x00\x99\x01\x00\x00\x7B\x01\x00\x00" -"\x3C\x00\x00\x00\x3D\x00\x04\x00\x06\x00\x00\x00\x9A\x01\x00\x00\x99\x01\x00\x00\x85\x00\x05\x00\x06\x00\x00\x00\x9B\x01\x00\x00" -"\x98\x01\x00\x00\x9A\x01\x00\x00\x0C\x00\x07\x00\x06\x00\x00\x00\x9C\x01\x00\x00\x01\x00\x00\x00\x1A\x00\x00\x00\x97\x01\x00\x00" -"\x9B\x01\x00\x00\x3E\x00\x03\x00\x93\x01\x00\x00\x9C\x01\x00\x00\x3D\x00\x04\x00\x06\x00\x00\x00\x9D\x01\x00\x00\x93\x01\x00\x00" -"\x85\x00\x05\x00\x06\x00\x00\x00\x9E\x01\x00\x00\x9D\x01\x00\x00\x1A\x01\x00\x00\x3E\x00\x03\x00\x93\x01\x00\x00\x9E\x01\x00\x00" -"\x3D\x00\x04\x00\x06\x00\x00\x00\x9F\x01\x00\x00\x93\x01\x00\x00\x3D\x00\x04\x00\x0D\x00\x00\x00\xA0\x01\x00\x00\x7B\x01\x00\x00" -"\x4F\x00\x08\x00\x07\x00\x00\x00\xA1\x01\x00\x00\xA0\x01\x00\x00\xA0\x01\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x02\x00\x00\x00" -"\x8E\x00\x05\x00\x07\x00\x00\x00\xA2\x01\x00\x00\xA1\x01\x00\x00\x9F\x01\x00\x00\x3D\x00\x04\x00\x0D\x00\x00\x00\xA3\x01\x00\x00" -"\x11\x01\x00\x00\x4F\x00\x08\x00\x07\x00\x00\x00\xA4\x01\x00\x00\xA3\x01\x00\x00\xA3\x01\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00" -"\x02\x00\x00\x00\x81\x00\x05\x00\x07\x00\x00\x00\xA5\x01\x00\x00\xA4\x01\x00\x00\xA2\x01\x00\x00\x3D\x00\x04\x00\x0D\x00\x00\x00" -"\xA6\x01\x00\x00\x11\x01\x00\x00\x4F\x00\x09\x00\x0D\x00\x00\x00\xA7\x01\x00\x00\xA6\x01\x00\x00\xA5\x01\x00\x00\x04\x00\x00\x00" -"\x05\x00\x00\x00\x06\x00\x00\x00\x03\x00\x00\x00\x3E\x00\x03\x00\x11\x01\x00\x00\xA7\x01\x00\x00\xF9\x00\x02\x00\x7A\x01\x00\x00" -"\xF8\x00\x02\x00\x7A\x01\x00\x00\xF7\x00\x03\x00\xAA\x01\x00\x00\x00\x00\x00\x00\xFA\x00\x04\x00\xA8\x01\x00\x00\xA9\x01\x00\x00" -"\xAA\x01\x00\x00\xF8\x00\x02\x00\xA9\x01\x00\x00\x3D\x00\x04\x00\x07\x00\x00\x00\xAC\x01\x00\x00\x0A\x01\x00\x00\x7F\x00\x04\x00" -"\x07\x00\x00\x00\xAD\x01\x00\x00\xAC\x01\x00\x00\x3D\x00\x04\x00\x07\x00\x00\x00\xAE\x01\x00\x00\x23\x01\x00\x00\x0C\x00\x07\x00" -"\x07\x00\x00\x00\xAF\x01\x00\x00\x01\x00\x00\x00\x47\x00\x00\x00\xAD\x01\x00\x00\xAE\x01\x00\x00\x3E\x00\x03\x00\xAB\x01\x00\x00" -"\xAF\x01\x00\x00\x41\x00\x05\x00\x28\x00\x00\x00\xB1\x01\x00\x00\xAB\x01\x00\x00\xB0\x01\x00\x00\x3D\x00\x04\x00\x06\x00\x00\x00" -"\xB2\x01\x00\x00\xB1\x01\x00\x00\x41\x00\x05\x00\x09\x01\x00\x00\xB6\x01\x00\x00\xB5\x01\x00\x00\x20\x00\x00\x00\x3D\x00\x04\x00" -"\x07\x00\x00\x00\xB7\x01\x00\x00\xB6\x01\x00\x00\x8E\x00\x05\x00\x07\x00\x00\x00\xB8\x01\x00\x00\xB7\x01\x00\x00\xB2\x01\x00\x00" -"\x41\x00\x05\x00\x28\x00\x00\x00\xBA\x01\x00\x00\xAB\x01\x00\x00\xB9\x01\x00\x00\x3D\x00\x04\x00\x06\x00\x00\x00\xBB\x01\x00\x00" -"\xBA\x01\x00\x00\x41\x00\x05\x00\x09\x01\x00\x00\xBD\x01\x00\x00\xB5\x01\x00\x00\xBC\x01\x00\x00\x3D\x00\x04\x00\x07\x00\x00\x00" -"\xBE\x01\x00\x00\xBD\x01\x00\x00\x8E\x00\x05\x00\x07\x00\x00\x00\xBF\x01\x00\x00\xBE\x01\x00\x00\xBB\x01\x00\x00\x81\x00\x05\x00" -"\x07\x00\x00\x00\xC0\x01\x00\x00\xB8\x01\x00\x00\xBF\x01\x00\x00\x41\x00\x05\x00\x28\x00\x00\x00\xC1\x01\x00\x00\xAB\x01\x00\x00" -"\x37\x00\x00\x00\x3D\x00\x04\x00\x06\x00\x00\x00\xC2\x01\x00\x00\xC1\x01\x00\x00\x41\x00\x05\x00\x09\x01\x00\x00\xC4\x01\x00\x00" -"\xB5\x01\x00\x00\xC3\x01\x00\x00\x3D\x00\x04\x00\x07\x00\x00\x00\xC5\x01\x00\x00\xC4\x01\x00\x00\x8E\x00\x05\x00\x07\x00\x00\x00" -"\xC6\x01\x00\x00\xC5\x01\x00\x00\xC2\x01\x00\x00\x81\x00\x05\x00\x07\x00\x00\x00\xC7\x01\x00\x00\xC0\x01\x00\x00\xC6\x01\x00\x00" -"\x3E\x00\x03\x00\xAB\x01\x00\x00\xC7\x01\x00\x00\x41\x00\x05\x00\xC8\x01\x00\x00\xC9\x01\x00\x00\x30\x00\x00\x00\xBC\x01\x00\x00" -"\x3D\x00\x04\x00\x2A\x00\x00\x00\xCA\x01\x00\x00\xC9\x01\x00\x00\x3D\x00\x04\x00\x07\x00\x00\x00\xCB\x01\x00\x00\xAB\x01\x00\x00" -"\x51\x00\x05\x00\x06\x00\x00\x00\xCC\x01\x00\x00\xCB\x01\x00\x00\x00\x00\x00\x00\x51\x00\x05\x00\x06\x00\x00\x00\xCD\x01\x00\x00" -"\xCB\x01\x00\x00\x01\x00\x00\x00\x51\x00\x05\x00\x06\x00\x00\x00\xCE\x01\x00\x00\xCB\x01\x00\x00\x02\x00\x00\x00\x50\x00\x07\x00" -"\x0D\x00\x00\x00\xCF\x01\x00\x00\xCC\x01\x00\x00\xCD\x01\x00\x00\xCE\x01\x00\x00\x40\x00\x00\x00\x91\x00\x05\x00\x0D\x00\x00\x00" -"\xD0\x01\x00\x00\xCA\x01\x00\x00\xCF\x01\x00\x00\x4F\x00\x08\x00\x07\x00\x00\x00\xD1\x01\x00\x00\xD0\x01\x00\x00\xD0\x01\x00\x00" -"\x00\x00\x00\x00\x01\x00\x00\x00\x02\x00\x00\x00\x3E\x00\x03\x00\xAB\x01\x00\x00\xD1\x01\x00\x00\x3D\x00\x04\x00\x14\x00\x00\x00" -"\xD3\x01\x00\x00\xD2\x01\x00\x00\x3D\x00\x04\x00\x16\x00\x00\x00\xD4\x01\x00\x00\x01\x01\x00\x00\x57\x00\x05\x00\x0D\x00\x00\x00" -"\xD5\x01\x00\x00\xD3\x01\x00\x00\xD4\x01\x00\x00\x4F\x00\x08\x00\x07\x00\x00\x00\xD6\x01\x00\x00\xD5\x01\x00\x00\xD5\x01\x00\x00" -"\x00\x00\x00\x00\x01\x00\x00\x00\x02\x00\x00\x00\x3D\x00\x04\x00\xD8\x01\x00\x00\xDB\x01\x00\x00\xDA\x01\x00\x00\x3D\x00\x04\x00" -"\x07\x00\x00\x00\xDC\x01\x00\x00\xAB\x01\x00\x00\x57\x00\x05\x00\x0D\x00\x00\x00\xDD\x01\x00\x00\xDB\x01\x00\x00\xDC\x01\x00\x00" -"\x4F\x00\x08\x00\x07\x00\x00\x00\xDE\x01\x00\x00\xDD\x01\x00\x00\xDD\x01\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x02\x00\x00\x00" -"\x85\x00\x05\x00\x07\x00\x00\x00\xDF\x01\x00\x00\xD6\x01\x00\x00\xDE\x01\x00\x00\x3D\x00\x04\x00\x0D\x00\x00\x00\xE0\x01\x00\x00" -"\x11\x01\x00\x00\x4F\x00\x08\x00\x07\x00\x00\x00\xE1\x01\x00\x00\xE0\x01\x00\x00\xE0\x01\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00" -"\x02\x00\x00\x00\x81\x00\x05\x00\x07\x00\x00\x00\xE2\x01\x00\x00\xE1\x01\x00\x00\xDF\x01\x00\x00\x3D\x00\x04\x00\x0D\x00\x00\x00" -"\xE3\x01\x00\x00\x11\x01\x00\x00\x4F\x00\x09\x00\x0D\x00\x00\x00\xE4\x01\x00\x00\xE3\x01\x00\x00\xE2\x01\x00\x00\x04\x00\x00\x00" -"\x05\x00\x00\x00\x06\x00\x00\x00\x03\x00\x00\x00\x3E\x00\x03\x00\x11\x01\x00\x00\xE4\x01\x00\x00\xF9\x00\x02\x00\xAA\x01\x00\x00" -"\xF8\x00\x02\x00\xAA\x01\x00\x00\xF7\x00\x03\x00\xE7\x01\x00\x00\x00\x00\x00\x00\xFA\x00\x04\x00\xE5\x01\x00\x00\xE6\x01\x00\x00" -"\x11\x02\x00\x00\xF8\x00\x02\x00\xE6\x01\x00\x00\x3D\x00\x04\x00\x07\x00\x00\x00\xE8\x01\x00\x00\x37\x01\x00\x00\x8E\x00\x05\x00" -"\x07\x00\x00\x00\xE9\x01\x00\x00\xE8\x01\x00\x00\xC2\x00\x00\x00\x3E\x00\x03\x00\x37\x01\x00\x00\xE9\x01\x00\x00\x3D\x00\x04\x00" -"\x14\x00\x00\x00\xEC\x01\x00\x00\xEB\x01\x00\x00\x3D\x00\x04\x00\x16\x00\x00\x00\xED\x01\x00\x00\x01\x01\x00\x00\x57\x00\x05\x00" -"\x0D\x00\x00\x00\xEE\x01\x00\x00\xEC\x01\x00\x00\xED\x01\x00\x00\x51\x00\x05\x00\x06\x00\x00\x00\xEF\x01\x00\x00\xEE\x01\x00\x00" -"\x00\x00\x00\x00\x3E\x00\x03\x00\xEA\x01\x00\x00\xEF\x01\x00\x00\x3D\x00\x04\x00\x07\x00\x00\x00\xF1\x01\x00\x00\x37\x01\x00\x00" -"\x50\x00\x06\x00\x07\x00\x00\x00\xF2\x01\x00\x00\xF0\x01\x00\x00\xF0\x01\x00\x00\xF0\x01\x00\x00\x83\x00\x05\x00\x07\x00\x00\x00" -"\xF3\x01\x00\x00\xF1\x01\x00\x00\xF2\x01\x00\x00\x3E\x00\x03\x00\x37\x01\x00\x00\xF3\x01\x00\x00\x3D\x00\x04\x00\x14\x00\x00\x00" -"\xF5\x01\x00\x00\xF4\x01\x00\x00\x3D\x00\x04\x00\x06\x00\x00\x00\xF6\x01\x00\x00\xEA\x01\x00\x00\x41\x00\x05\x00\x28\x00\x00\x00" -"\xF7\x01\x00\x00\x37\x01\x00\x00\xB0\x01\x00\x00\x3D\x00\x04\x00\x06\x00\x00\x00\xF8\x01\x00\x00\xF7\x01\x00\x00\x83\x00\x05\x00" -"\x06\x00\x00\x00\xF9\x01\x00\x00\x54\x00\x00\x00\xF8\x01\x00\x00\x50\x00\x05\x00\x16\x00\x00\x00\xFA\x01\x00\x00\xF6\x01\x00\x00" -"\xF9\x01\x00\x00\x57\x00\x05\x00\x0D\x00\x00\x00\xFB\x01\x00\x00\xF5\x01\x00\x00\xFA\x01\x00\x00\x51\x00\x05\x00\x06\x00\x00\x00" -"\xFC\x01\x00\x00\xFB\x01\x00\x00\x00\x00\x00\x00\x41\x00\x05\x00\xFD\x01\x00\x00\xFE\x01\x00\x00\x11\x01\x00\x00\xB0\x01\x00\x00" -"\x3E\x00\x03\x00\xFE\x01\x00\x00\xFC\x01\x00\x00\x3D\x00\x04\x00\x14\x00\x00\x00\xFF\x01\x00\x00\xF4\x01\x00\x00\x3D\x00\x04\x00" -"\x06\x00\x00\x00\x00\x02\x00\x00\xEA\x01\x00\x00\x41\x00\x05\x00\x28\x00\x00\x00\x01\x02\x00\x00\x37\x01\x00\x00\xB9\x01\x00\x00" -"\x3D\x00\x04\x00\x06\x00\x00\x00\x02\x02\x00\x00\x01\x02\x00\x00\x83\x00\x05\x00\x06\x00\x00\x00\x03\x02\x00\x00\x54\x00\x00\x00" -"\x02\x02\x00\x00\x50\x00\x05\x00\x16\x00\x00\x00\x04\x02\x00\x00\x00\x02\x00\x00\x03\x02\x00\x00\x57\x00\x05\x00\x0D\x00\x00\x00" -"\x05\x02\x00\x00\xFF\x01\x00\x00\x04\x02\x00\x00\x51\x00\x05\x00\x06\x00\x00\x00\x06\x02\x00\x00\x05\x02\x00\x00\x01\x00\x00\x00" -"\x41\x00\x05\x00\xFD\x01\x00\x00\x07\x02\x00\x00\x11\x01\x00\x00\xB9\x01\x00\x00\x3E\x00\x03\x00\x07\x02\x00\x00\x06\x02\x00\x00" -"\x3D\x00\x04\x00\x14\x00\x00\x00\x08\x02\x00\x00\xF4\x01\x00\x00\x3D\x00\x04\x00\x06\x00\x00\x00\x09\x02\x00\x00\xEA\x01\x00\x00" -"\x41\x00\x05\x00\x28\x00\x00\x00\x0A\x02\x00\x00\x37\x01\x00\x00\x37\x00\x00\x00\x3D\x00\x04\x00\x06\x00\x00\x00\x0B\x02\x00\x00" -"\x0A\x02\x00\x00\x83\x00\x05\x00\x06\x00\x00\x00\x0C\x02\x00\x00\x54\x00\x00\x00\x0B\x02\x00\x00\x50\x00\x05\x00\x16\x00\x00\x00" -"\x0D\x02\x00\x00\x09\x02\x00\x00\x0C\x02\x00\x00\x57\x00\x05\x00\x0D\x00\x00\x00\x0E\x02\x00\x00\x08\x02\x00\x00\x0D\x02\x00\x00" -"\x51\x00\x05\x00\x06\x00\x00\x00\x0F\x02\x00\x00\x0E\x02\x00\x00\x02\x00\x00\x00\x41\x00\x05\x00\xFD\x01\x00\x00\x10\x02\x00\x00" -"\x11\x01\x00\x00\x37\x00\x00\x00\x3E\x00\x03\x00\x10\x02\x00\x00\x0F\x02\x00\x00\xF9\x00\x02\x00\xE7\x01\x00\x00\xF8\x00\x02\x00" -"\x11\x02\x00\x00\x3D\x00\x04\x00\x07\x00\x00\x00\x12\x02\x00\x00\x37\x01\x00\x00\x3D\x00\x04\x00\x0D\x00\x00\x00\x13\x02\x00\x00" -"\x11\x01\x00\x00\x4F\x00\x08\x00\x07\x00\x00\x00\x14\x02\x00\x00\x13\x02\x00\x00\x13\x02\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00" -"\x02\x00\x00\x00\x85\x00\x05\x00\x07\x00\x00\x00\x15\x02\x00\x00\x14\x02\x00\x00\x12\x02\x00\x00\x3D\x00\x04\x00\x0D\x00\x00\x00" -"\x16\x02\x00\x00\x11\x01\x00\x00\x4F\x00\x09\x00\x0D\x00\x00\x00\x17\x02\x00\x00\x16\x02\x00\x00\x15\x02\x00\x00\x04\x00\x00\x00" -"\x05\x00\x00\x00\x06\x00\x00\x00\x03\x00\x00\x00\x3E\x00\x03\x00\x11\x01\x00\x00\x17\x02\x00\x00\xF7\x00\x03\x00\x1B\x02\x00\x00" -"\x00\x00\x00\x00\xFA\x00\x04\x00\x19\x02\x00\x00\x1A\x02\x00\x00\x1B\x02\x00\x00\xF8\x00\x02\x00\x1A\x02\x00\x00\x3D\x00\x04\x00" -"\x14\x00\x00\x00\x1D\x02\x00\x00\x1C\x02\x00\x00\x3D\x00\x04\x00\x16\x00\x00\x00\x1E\x02\x00\x00\x01\x01\x00\x00\x57\x00\x05\x00" -"\x0D\x00\x00\x00\x1F\x02\x00\x00\x1D\x02\x00\x00\x1E\x02\x00\x00\x4F\x00\x08\x00\x07\x00\x00\x00\x20\x02\x00\x00\x1F\x02\x00\x00" -"\x1F\x02\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x02\x00\x00\x00\x3D\x00\x04\x00\x0D\x00\x00\x00\x21\x02\x00\x00\x11\x01\x00\x00" -"\x4F\x00\x08\x00\x07\x00\x00\x00\x22\x02\x00\x00\x21\x02\x00\x00\x21\x02\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x02\x00\x00\x00" -"\x81\x00\x05\x00\x07\x00\x00\x00\x23\x02\x00\x00\x22\x02\x00\x00\x20\x02\x00\x00\x3D\x00\x04\x00\x0D\x00\x00\x00\x24\x02\x00\x00" -"\x11\x01\x00\x00\x4F\x00\x09\x00\x0D\x00\x00\x00\x25\x02\x00\x00\x24\x02\x00\x00\x23\x02\x00\x00\x04\x00\x00\x00\x05\x00\x00\x00" -"\x06\x00\x00\x00\x03\x00\x00\x00\x3E\x00\x03\x00\x11\x01\x00\x00\x25\x02\x00\x00\xF9\x00\x02\x00\x1B\x02\x00\x00\xF8\x00\x02\x00" -"\x1B\x02\x00\x00\xF9\x00\x02\x00\xE7\x01\x00\x00\xF8\x00\x02\x00\xE7\x01\x00\x00\x3D\x00\x04\x00\x0D\x00\x00\x00\x26\x02\x00\x00" -"\x11\x01\x00\x00\x41\x00\x05\x00\x5F\x00\x00\x00\x28\x02\x00\x00\x30\x00\x00\x00\x27\x02\x00\x00\x3D\x00\x04\x00\x0D\x00\x00\x00" -"\x29\x02\x00\x00\x28\x02\x00\x00\x85\x00\x05\x00\x0D\x00\x00\x00\x2A\x02\x00\x00\x26\x02\x00\x00\x29\x02\x00\x00\x3E\x00\x03\x00" -"\x11\x01\x00\x00\x2A\x02\x00\x00\xB6\x00\x05\x00\x21\x00\x00\x00\x2C\x02\x00\x00\x2B\x02\x00\x00\x54\x00\x00\x00\xF7\x00\x03\x00" -"\x2E\x02\x00\x00\x00\x00\x00\x00\xFA\x00\x04\x00\x2C\x02\x00\x00\x2D\x02\x00\x00\x2E\x02\x00\x00\xF8\x00\x02\x00\x2D\x02\x00\x00" -"\xF7\x00\x03\x00\x32\x02\x00\x00\x00\x00\x00\x00\xFA\x00\x04\x00\x30\x02\x00\x00\x31\x02\x00\x00\x39\x02\x00\x00\xF8\x00\x02\x00" -"\x31\x02\x00\x00\x41\x00\x05\x00\xFD\x01\x00\x00\x33\x02\x00\x00\x11\x01\x00\x00\x3C\x00\x00\x00\x3D\x00\x04\x00\x06\x00\x00\x00" -"\x34\x02\x00\x00\x33\x02\x00\x00\xB8\x00\x05\x00\x21\x00\x00\x00\x35\x02\x00\x00\x34\x02\x00\x00\x2B\x02\x00\x00\xF7\x00\x03\x00" -"\x37\x02\x00\x00\x00\x00\x00\x00\xFA\x00\x04\x00\x35\x02\x00\x00\x36\x02\x00\x00\x37\x02\x00\x00\xF8\x00\x02\x00\x36\x02\x00\x00" -"\xFC\x00\x01\x00\xF8\x00\x02\x00\x37\x02\x00\x00\xF9\x00\x02\x00\x32\x02\x00\x00\xF8\x00\x02\x00\x39\x02\x00\x00\x41\x00\x05\x00" -"\xFD\x01\x00\x00\x3A\x02\x00\x00\x11\x01\x00\x00\x3C\x00\x00\x00\x3D\x00\x04\x00\x06\x00\x00\x00\x3B\x02\x00\x00\x3A\x02\x00\x00" -"\xBE\x00\x05\x00\x21\x00\x00\x00\x3C\x02\x00\x00\x3B\x02\x00\x00\x2B\x02\x00\x00\xF7\x00\x03\x00\x3E\x02\x00\x00\x00\x00\x00\x00" -"\xFA\x00\x04\x00\x3C\x02\x00\x00\x3D\x02\x00\x00\x3E\x02\x00\x00\xF8\x00\x02\x00\x3D\x02\x00\x00\xFC\x00\x01\x00\xF8\x00\x02\x00" -"\x3E\x02\x00\x00\xF9\x00\x02\x00\x32\x02\x00\x00\xF8\x00\x02\x00\x32\x02\x00\x00\x41\x00\x05\x00\xFD\x01\x00\x00\x40\x02\x00\x00" -"\x11\x01\x00\x00\x3C\x00\x00\x00\x3E\x00\x03\x00\x40\x02\x00\x00\x54\x00\x00\x00\xF9\x00\x02\x00\x2E\x02\x00\x00\xF8\x00\x02\x00" -"\x2E\x02\x00\x00\x3D\x00\x04\x00\x0D\x00\x00\x00\x42\x02\x00\x00\x11\x01\x00\x00\x3E\x00\x03\x00\x41\x02\x00\x00\x42\x02\x00\x00" -"\x39\x00\x05\x00\x0D\x00\x00\x00\x43\x02\x00\x00\x11\x00\x00\x00\x41\x02\x00\x00\x3E\x00\x03\x00\x11\x01\x00\x00\x43\x02\x00\x00" -"\xFD\x00\x01\x00\x38\x00\x01\x00\x36\x00\x05\x00\x07\x00\x00\x00\x0B\x00\x00\x00\x00\x00\x00\x00\x09\x00\x00\x00\x37\x00\x03\x00" -"\x08\x00\x00\x00\x0A\x00\x00\x00\xF8\x00\x02\x00\x0C\x00\x00\x00\x3B\x00\x04\x00\x28\x00\x00\x00\x29\x00\x00\x00\x07\x00\x00\x00" -"\x3B\x00\x04\x00\x28\x00\x00\x00\x4E\x00\x00\x00\x07\x00\x00\x00\xF7\x00\x03\x00\x25\x00\x00\x00\x00\x00\x00\x00\xFA\x00\x04\x00" -"\x23\x00\x00\x00\x24\x00\x00\x00\x25\x00\x00\x00\xF8\x00\x02\x00\x24\x00\x00\x00\x3D\x00\x04\x00\x07\x00\x00\x00\x26\x00\x00\x00" -"\x0A\x00\x00\x00\xFE\x00\x02\x00\x26\x00\x00\x00\xF8\x00\x02\x00\x25\x00\x00\x00\x41\x00\x05\x00\x32\x00\x00\x00\x33\x00\x00\x00" -"\x30\x00\x00\x00\x31\x00\x00\x00\x3D\x00\x04\x00\x06\x00\x00\x00\x34\x00\x00\x00\x33\x00\x00\x00\x41\x00\x05\x00\x38\x00\x00\x00" -"\x39\x00\x00\x00\x36\x00\x00\x00\x37\x00\x00\x00\x3D\x00\x04\x00\x06\x00\x00\x00\x3A\x00\x00\x00\x39\x00\x00\x00\x85\x00\x05\x00" -"\x06\x00\x00\x00\x3B\x00\x00\x00\x34\x00\x00\x00\x3A\x00\x00\x00\x41\x00\x05\x00\x38\x00\x00\x00\x3D\x00\x00\x00\x36\x00\x00\x00" -"\x3C\x00\x00\x00\x3D\x00\x04\x00\x06\x00\x00\x00\x3E\x00\x00\x00\x3D\x00\x00\x00\x88\x00\x05\x00\x06\x00\x00\x00\x3F\x00\x00\x00" -"\x3B\x00\x00\x00\x3E\x00\x00\x00\x3E\x00\x03\x00\x29\x00\x00\x00\x3F\x00\x00\x00\x3D\x00\x04\x00\x06\x00\x00\x00\x41\x00\x00\x00" -"\x29\x00\x00\x00\x41\x00\x05\x00\x32\x00\x00\x00\x43\x00\x00\x00\x30\x00\x00\x00\x42\x00\x00\x00\x3D\x00\x04\x00\x06\x00\x00\x00" -"\x44\x00\x00\x00\x43\x00\x00\x00\x83\x00\x05\x00\x06\x00\x00\x00\x45\x00\x00\x00\x41\x00\x00\x00\x44\x00\x00\x00\x0C\x00\x07\x00" -"\x06\x00\x00\x00\x46\x00\x00\x00\x01\x00\x00\x00\x28\x00\x00\x00\x40\x00\x00\x00\x45\x00\x00\x00\x3E\x00\x03\x00\x29\x00\x00\x00" -"\x46\x00\x00\x00\xF7\x00\x03\x00\x4A\x00\x00\x00\x00\x00\x00\x00\xFA\x00\x04\x00\x48\x00\x00\x00\x49\x00\x00\x00\x4A\x00\x00\x00" -"\xF8\x00\x02\x00\x49\x00\x00\x00\x3D\x00\x04\x00\x06\x00\x00\x00\x4B\x00\x00\x00\x29\x00\x00\x00\x3D\x00\x04\x00\x06\x00\x00\x00" -"\x4C\x00\x00\x00\x29\x00\x00\x00\x85\x00\x05\x00\x06\x00\x00\x00\x4D\x00\x00\x00\x4C\x00\x00\x00\x4B\x00\x00\x00\x3E\x00\x03\x00" -"\x29\x00\x00\x00\x4D\x00\x00\x00\xF9\x00\x02\x00\x4A\x00\x00\x00\xF8\x00\x02\x00\x4A\x00\x00\x00\x3D\x00\x04\x00\x06\x00\x00\x00" -"\x4F\x00\x00\x00\x29\x00\x00\x00\x85\x00\x05\x00\x06\x00\x00\x00\x51\x00\x00\x00\x4F\x00\x00\x00\x50\x00\x00\x00\x7F\x00\x04\x00" -"\x06\x00\x00\x00\x52\x00\x00\x00\x51\x00\x00\x00\x0C\x00\x06\x00\x06\x00\x00\x00\x53\x00\x00\x00\x01\x00\x00\x00\x1D\x00\x00\x00" -"\x52\x00\x00\x00\x3E\x00\x03\x00\x4E\x00\x00\x00\x53\x00\x00\x00\x41\x00\x06\x00\x32\x00\x00\x00\x56\x00\x00\x00\x30\x00\x00\x00" -"\x55\x00\x00\x00\x3C\x00\x00\x00\x3D\x00\x04\x00\x06\x00\x00\x00\x57\x00\x00\x00\x56\x00\x00\x00\x83\x00\x05\x00\x06\x00\x00\x00" -"\x58\x00\x00\x00\x54\x00\x00\x00\x57\x00\x00\x00\x3D\x00\x04\x00\x06\x00\x00\x00\x59\x00\x00\x00\x4E\x00\x00\x00\x0C\x00\x08\x00" -"\x06\x00\x00\x00\x5A\x00\x00\x00\x01\x00\x00\x00\x2B\x00\x00\x00\x59\x00\x00\x00\x40\x00\x00\x00\x54\x00\x00\x00\x41\x00\x06\x00" -"\x32\x00\x00\x00\x5B\x00\x00\x00\x30\x00\x00\x00\x55\x00\x00\x00\x3C\x00\x00\x00\x3D\x00\x04\x00\x06\x00\x00\x00\x5C\x00\x00\x00" -"\x5B\x00\x00\x00\x85\x00\x05\x00\x06\x00\x00\x00\x5D\x00\x00\x00\x5A\x00\x00\x00\x5C\x00\x00\x00\x81\x00\x05\x00\x06\x00\x00\x00" -"\x5E\x00\x00\x00\x58\x00\x00\x00\x5D\x00\x00\x00\x3E\x00\x03\x00\x4E\x00\x00\x00\x5E\x00\x00\x00\x41\x00\x05\x00\x5F\x00\x00\x00" -"\x60\x00\x00\x00\x30\x00\x00\x00\x55\x00\x00\x00\x3D\x00\x04\x00\x0D\x00\x00\x00\x61\x00\x00\x00\x60\x00\x00\x00\x4F\x00\x08\x00" -"\x07\x00\x00\x00\x62\x00\x00\x00\x61\x00\x00\x00\x61\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x02\x00\x00\x00\x3D\x00\x04\x00" -"\x07\x00\x00\x00\x63\x00\x00\x00\x0A\x00\x00\x00\x3D\x00\x04\x00\x06\x00\x00\x00\x64\x00\x00\x00\x4E\x00\x00\x00\x50\x00\x06\x00" -"\x07\x00\x00\x00\x65\x00\x00\x00\x64\x00\x00\x00\x64\x00\x00\x00\x64\x00\x00\x00\x0C\x00\x08\x00\x07\x00\x00\x00\x66\x00\x00\x00" -"\x01\x00\x00\x00\x2E\x00\x00\x00\x62\x00\x00\x00\x63\x00\x00\x00\x65\x00\x00\x00\xFE\x00\x02\x00\x66\x00\x00\x00\x38\x00\x01\x00" -"\x36\x00\x05\x00\x0D\x00\x00\x00\x11\x00\x00\x00\x00\x00\x00\x00\x0F\x00\x00\x00\x37\x00\x03\x00\x0E\x00\x00\x00\x10\x00\x00\x00" -"\xF8\x00\x02\x00\x12\x00\x00\x00\x3B\x00\x04\x00\x08\x00\x00\x00\x6F\x00\x00\x00\x07\x00\x00\x00\xF7\x00\x03\x00\x6C\x00\x00\x00" -"\x00\x00\x00\x00\xFA\x00\x04\x00\x6A\x00\x00\x00\x6B\x00\x00\x00\x6C\x00\x00\x00\xF8\x00\x02\x00\x6B\x00\x00\x00\x3D\x00\x04\x00" -"\x0D\x00\x00\x00\x6D\x00\x00\x00\x10\x00\x00\x00\xFE\x00\x02\x00\x6D\x00\x00\x00\xF8\x00\x02\x00\x6C\x00\x00\x00\x3D\x00\x04\x00" -"\x0D\x00\x00\x00\x70\x00\x00\x00\x10\x00\x00\x00\x4F\x00\x08\x00\x07\x00\x00\x00\x71\x00\x00\x00\x70\x00\x00\x00\x70\x00\x00\x00" -"\x00\x00\x00\x00\x01\x00\x00\x00\x02\x00\x00\x00\x3E\x00\x03\x00\x6F\x00\x00\x00\x71\x00\x00\x00\x39\x00\x05\x00\x07\x00\x00\x00" -"\x72\x00\x00\x00\x0B\x00\x00\x00\x6F\x00\x00\x00\x51\x00\x05\x00\x06\x00\x00\x00\x73\x00\x00\x00\x72\x00\x00\x00\x00\x00\x00\x00" -"\x51\x00\x05\x00\x06\x00\x00\x00\x74\x00\x00\x00\x72\x00\x00\x00\x01\x00\x00\x00\x51\x00\x05\x00\x06\x00\x00\x00\x75\x00\x00\x00" -"\x72\x00\x00\x00\x02\x00\x00\x00\x50\x00\x07\x00\x0D\x00\x00\x00\x76\x00\x00\x00\x73\x00\x00\x00\x74\x00\x00\x00\x75\x00\x00\x00" -"\x54\x00\x00\x00\x41\x00\x05\x00\x28\x00\x00\x00\x77\x00\x00\x00\x10\x00\x00\x00\x3C\x00\x00\x00\x3D\x00\x04\x00\x06\x00\x00\x00" -"\x78\x00\x00\x00\x77\x00\x00\x00\x8E\x00\x05\x00\x0D\x00\x00\x00\x79\x00\x00\x00\x76\x00\x00\x00\x78\x00\x00\x00\xFE\x00\x02\x00" -"\x79\x00\x00\x00\x38\x00\x01\x00\x36\x00\x05\x00\x16\x00\x00\x00\x1C\x00\x00\x00\x00\x00\x00\x00\x18\x00\x00\x00\x37\x00\x03\x00" -"\x15\x00\x00\x00\x19\x00\x00\x00\x37\x00\x03\x00\x17\x00\x00\x00\x1A\x00\x00\x00\x37\x00\x03\x00\x08\x00\x00\x00\x1B\x00\x00\x00" -"\xF8\x00\x02\x00\x1D\x00\x00\x00\x3B\x00\x04\x00\x08\x00\x00\x00\x7F\x00\x00\x00\x07\x00\x00\x00\x3B\x00\x04\x00\x08\x00\x00\x00" -"\x8C\x00\x00\x00\x07\x00\x00\x00\x3B\x00\x04\x00\x28\x00\x00\x00\x98\x00\x00\x00\x07\x00\x00\x00\x3B\x00\x04\x00\x28\x00\x00\x00" -"\xAE\x00\x00\x00\x07\x00\x00\x00\x3B\x00\x04\x00\x17\x00\x00\x00\xD5\x00\x00\x00\x07\x00\x00\x00\x3B\x00\x04\x00\x17\x00\x00\x00" -"\xDC\x00\x00\x00\x07\x00\x00\x00\xF7\x00\x03\x00\x7E\x00\x00\x00\x00\x00\x00\x00\xFA\x00\x04\x00\x7C\x00\x00\x00\x7D\x00\x00\x00" -"\xD0\x00\x00\x00\xF8\x00\x02\x00\x7D\x00\x00\x00\x3D\x00\x04\x00\x07\x00\x00\x00\x80\x00\x00\x00\x1B\x00\x00\x00\x0C\x00\x06\x00" -"\x07\x00\x00\x00\x81\x00\x00\x00\x01\x00\x00\x00\x45\x00\x00\x00\x80\x00\x00\x00\x4F\x00\x07\x00\x16\x00\x00\x00\x82\x00\x00\x00" -"\x81\x00\x00\x00\x81\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x8E\x00\x05\x00\x16\x00\x00\x00\x84\x00\x00\x00\x82\x00\x00\x00" -"\x83\x00\x00\x00\x8E\x00\x05\x00\x16\x00\x00\x00\x85\x00\x00\x00\x84\x00\x00\x00\x54\x00\x00\x00\x85\x00\x05\x00\x16\x00\x00\x00" -"\x88\x00\x00\x00\x85\x00\x00\x00\x87\x00\x00\x00\x51\x00\x05\x00\x06\x00\x00\x00\x89\x00\x00\x00\x88\x00\x00\x00\x00\x00\x00\x00" -"\x51\x00\x05\x00\x06\x00\x00\x00\x8A\x00\x00\x00\x88\x00\x00\x00\x01\x00\x00\x00\x50\x00\x06\x00\x07\x00\x00\x00\x8B\x00\x00\x00" -"\x89\x00\x00\x00\x8A\x00\x00\x00\x86\x00\x00\x00\x3E\x00\x03\x00\x7F\x00\x00\x00\x8B\x00\x00\x00\x3D\x00\x04\x00\x16\x00\x00\x00" -"\x8D\x00\x00\x00\x1A\x00\x00\x00\x51\x00\x05\x00\x06\x00\x00\x00\x8E\x00\x00\x00\x8D\x00\x00\x00\x00\x00\x00\x00\x51\x00\x05\x00" -"\x06\x00\x00\x00\x8F\x00\x00\x00\x8D\x00\x00\x00\x01\x00\x00\x00\x50\x00\x05\x00\x16\x00\x00\x00\x90\x00\x00\x00\x8E\x00\x00\x00" -"\x8F\x00\x00\x00\x51\x00\x05\x00\x06\x00\x00\x00\x91\x00\x00\x00\x90\x00\x00\x00\x00\x00\x00\x00\x51\x00\x05\x00\x06\x00\x00\x00" -"\x92\x00\x00\x00\x90\x00\x00\x00\x01\x00\x00\x00\x50\x00\x06\x00\x07\x00\x00\x00\x93\x00\x00\x00\x91\x00\x00\x00\x92\x00\x00\x00" -"\x54\x00\x00\x00\x3E\x00\x03\x00\x8C\x00\x00\x00\x93\x00\x00\x00\x3D\x00\x04\x00\x07\x00\x00\x00\x95\x00\x00\x00\x7F\x00\x00\x00" -"\x50\x00\x06\x00\x07\x00\x00\x00\x96\x00\x00\x00\x94\x00\x00\x00\x94\x00\x00\x00\x94\x00\x00\x00\x88\x00\x05\x00\x07\x00\x00\x00" -"\x97\x00\x00\x00\x95\x00\x00\x00\x96\x00\x00\x00\x3E\x00\x03\x00\x7F\x00\x00\x00\x97\x00\x00\x00\x3E\x00\x03\x00\x98\x00\x00\x00" -"\x54\x00\x00\x00\xF9\x00\x02\x00\x99\x00\x00\x00\xF8\x00\x02\x00\x99\x00\x00\x00\xF6\x00\x04\x00\x9B\x00\x00\x00\x9C\x00\x00\x00" -"\x00\x00\x00\x00\xF9\x00\x02\x00\x9D\x00\x00\x00\xF8\x00\x02\x00\x9D\x00\x00\x00\x3D\x00\x04\x00\x06\x00\x00\x00\x9E\x00\x00\x00" -"\x98\x00\x00\x00\xB8\x00\x05\x00\x21\x00\x00\x00\x9F\x00\x00\x00\x9E\x00\x00\x00\x94\x00\x00\x00\xFA\x00\x04\x00\x9F\x00\x00\x00" -"\x9A\x00\x00\x00\x9B\x00\x00\x00\xF8\x00\x02\x00\x9A\x00\x00\x00\x3D\x00\x04\x00\x07\x00\x00\x00\xA0\x00\x00\x00\x7F\x00\x00\x00" -"\x3D\x00\x04\x00\x14\x00\x00\x00\xA1\x00\x00\x00\x19\x00\x00\x00\x3D\x00\x04\x00\x07\x00\x00\x00\xA2\x00\x00\x00\x8C\x00\x00\x00" -"\x4F\x00\x07\x00\x16\x00\x00\x00\xA3\x00\x00\x00\xA2\x00\x00\x00\xA2\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x57\x00\x05\x00" -"\x0D\x00\x00\x00\xA4\x00\x00\x00\xA1\x00\x00\x00\xA3\x00\x00\x00\x51\x00\x05\x00\x06\x00\x00\x00\xA5\x00\x00\x00\xA4\x00\x00\x00" -"\x03\x00\x00\x00\x41\x00\x05\x00\x28\x00\x00\x00\xA6\x00\x00\x00\x8C\x00\x00\x00\x37\x00\x00\x00\x3D\x00\x04\x00\x06\x00\x00\x00" -"\xA7\x00\x00\x00\xA6\x00\x00\x00\x0C\x00\x07\x00\x06\x00\x00\x00\xA8\x00\x00\x00\x01\x00\x00\x00\x30\x00\x00\x00\xA5\x00\x00\x00" -"\xA7\x00\x00\x00\x8E\x00\x05\x00\x07\x00\x00\x00\xA9\x00\x00\x00\xA0\x00\x00\x00\xA8\x00\x00\x00\x3D\x00\x04\x00\x07\x00\x00\x00" -"\xAA\x00\x00\x00\x8C\x00\x00\x00\x81\x00\x05\x00\x07\x00\x00\x00\xAB\x00\x00\x00\xAA\x00\x00\x00\xA9\x00\x00\x00\x3E\x00\x03\x00" -"\x8C\x00\x00\x00\xAB\x00\x00\x00\xF9\x00\x02\x00\x9C\x00\x00\x00\xF8\x00\x02\x00\x9C\x00\x00\x00\x3D\x00\x04\x00\x06\x00\x00\x00" -"\xAC\x00\x00\x00\x98\x00\x00\x00\x81\x00\x05\x00\x06\x00\x00\x00\xAD\x00\x00\x00\xAC\x00\x00\x00\x54\x00\x00\x00\x3E\x00\x03\x00" -"\x98\x00\x00\x00\xAD\x00\x00\x00\xF9\x00\x02\x00\x99\x00\x00\x00\xF8\x00\x02\x00\x9B\x00\x00\x00\x3E\x00\x03\x00\x98\x00\x00\x00" -"\x40\x00\x00\x00\x3E\x00\x03\x00\xAE\x00\x00\x00\x54\x00\x00\x00\xF9\x00\x02\x00\xAF\x00\x00\x00\xF8\x00\x02\x00\xAF\x00\x00\x00" -"\xF6\x00\x04\x00\xB1\x00\x00\x00\xB2\x00\x00\x00\x00\x00\x00\x00\xF9\x00\x02\x00\xB3\x00\x00\x00\xF8\x00\x02\x00\xB3\x00\x00\x00" -"\x3D\x00\x04\x00\x06\x00\x00\x00\xB4\x00\x00\x00\x98\x00\x00\x00\xB8\x00\x05\x00\x21\x00\x00\x00\xB6\x00\x00\x00\xB4\x00\x00\x00" -"\xB5\x00\x00\x00\xFA\x00\x04\x00\xB6\x00\x00\x00\xB0\x00\x00\x00\xB1\x00\x00\x00\xF8\x00\x02\x00\xB0\x00\x00\x00\x3D\x00\x04\x00" -"\x07\x00\x00\x00\xB7\x00\x00\x00\x7F\x00\x00\x00\x3D\x00\x04\x00\x14\x00\x00\x00\xB8\x00\x00\x00\x19\x00\x00\x00\x3D\x00\x04\x00" -"\x07\x00\x00\x00\xB9\x00\x00\x00\x8C\x00\x00\x00\x4F\x00\x07\x00\x16\x00\x00\x00\xBA\x00\x00\x00\xB9\x00\x00\x00\xB9\x00\x00\x00" -"\x00\x00\x00\x00\x01\x00\x00\x00\x57\x00\x05\x00\x0D\x00\x00\x00\xBB\x00\x00\x00\xB8\x00\x00\x00\xBA\x00\x00\x00\x51\x00\x05\x00" -"\x06\x00\x00\x00\xBC\x00\x00\x00\xBB\x00\x00\x00\x03\x00\x00\x00\x41\x00\x05\x00\x28\x00\x00\x00\xBD\x00\x00\x00\x8C\x00\x00\x00" -"\x37\x00\x00\x00\x3D\x00\x04\x00\x06\x00\x00\x00\xBE\x00\x00\x00\xBD\x00\x00\x00\x0C\x00\x07\x00\x06\x00\x00\x00\xBF\x00\x00\x00" -"\x01\x00\x00\x00\x30\x00\x00\x00\xBC\x00\x00\x00\xBE\x00\x00\x00\x3D\x00\x04\x00\x06\x00\x00\x00\xC0\x00\x00\x00\xAE\x00\x00\x00" -"\x85\x00\x05\x00\x06\x00\x00\x00\xC1\x00\x00\x00\xBF\x00\x00\x00\xC0\x00\x00\x00\x3D\x00\x04\x00\x06\x00\x00\x00\xC3\x00\x00\x00" -"\xAE\x00\x00\x00\x85\x00\x05\x00\x06\x00\x00\x00\xC4\x00\x00\x00\xC2\x00\x00\x00\xC3\x00\x00\x00\x83\x00\x05\x00\x06\x00\x00\x00" -"\xC5\x00\x00\x00\xC1\x00\x00\x00\xC4\x00\x00\x00\x8E\x00\x05\x00\x07\x00\x00\x00\xC6\x00\x00\x00\xB7\x00\x00\x00\xC5\x00\x00\x00" -"\x3D\x00\x04\x00\x07\x00\x00\x00\xC7\x00\x00\x00\x8C\x00\x00\x00\x81\x00\x05\x00\x07\x00\x00\x00\xC8\x00\x00\x00\xC7\x00\x00\x00" -"\xC6\x00\x00\x00\x3E\x00\x03\x00\x8C\x00\x00\x00\xC8\x00\x00\x00\xF9\x00\x02\x00\xB2\x00\x00\x00\xF8\x00\x02\x00\xB2\x00\x00\x00" -"\x3D\x00\x04\x00\x06\x00\x00\x00\xC9\x00\x00\x00\x98\x00\x00\x00\x81\x00\x05\x00\x06\x00\x00\x00\xCA\x00\x00\x00\xC9\x00\x00\x00" -"\x54\x00\x00\x00\x3E\x00\x03\x00\x98\x00\x00\x00\xCA\x00\x00\x00\x3D\x00\x04\x00\x06\x00\x00\x00\xCB\x00\x00\x00\xAE\x00\x00\x00" -"\x85\x00\x05\x00\x06\x00\x00\x00\xCC\x00\x00\x00\xCB\x00\x00\x00\xC2\x00\x00\x00\x3E\x00\x03\x00\xAE\x00\x00\x00\xCC\x00\x00\x00" -"\xF9\x00\x02\x00\xAF\x00\x00\x00\xF8\x00\x02\x00\xB1\x00\x00\x00\x3D\x00\x04\x00\x07\x00\x00\x00\xCD\x00\x00\x00\x8C\x00\x00\x00" -"\x4F\x00\x07\x00\x16\x00\x00\x00\xCE\x00\x00\x00\xCD\x00\x00\x00\xCD\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\xFE\x00\x02\x00" -"\xCE\x00\x00\x00\xF8\x00\x02\x00\xD0\x00\x00\x00\xBA\x00\x05\x00\x21\x00\x00\x00\xD2\x00\x00\x00\xD1\x00\x00\x00\x40\x00\x00\x00" -"\xF7\x00\x03\x00\xD4\x00\x00\x00\x00\x00\x00\x00\xFA\x00\x04\x00\xD2\x00\x00\x00\xD3\x00\x00\x00\xD4\x00\x00\x00\xF8\x00\x02\x00" -"\xD3\x00\x00\x00\x3D\x00\x04\x00\x07\x00\x00\x00\xD6\x00\x00\x00\x1B\x00\x00\x00\x0C\x00\x06\x00\x07\x00\x00\x00\xD7\x00\x00\x00" -"\x01\x00\x00\x00\x45\x00\x00\x00\xD6\x00\x00\x00\x4F\x00\x07\x00\x16\x00\x00\x00\xD8\x00\x00\x00\xD7\x00\x00\x00\xD7\x00\x00\x00" -"\x00\x00\x00\x00\x01\x00\x00\x00\x8E\x00\x05\x00\x16\x00\x00\x00\xD9\x00\x00\x00\xD8\x00\x00\x00\x83\x00\x00\x00\x8E\x00\x05\x00" -"\x16\x00\x00\x00\xDA\x00\x00\x00\xD9\x00\x00\x00\x54\x00\x00\x00\x85\x00\x05\x00\x16\x00\x00\x00\xDB\x00\x00\x00\xDA\x00\x00\x00" -"\x87\x00\x00\x00\x3E\x00\x03\x00\xD5\x00\x00\x00\xDB\x00\x00\x00\x3D\x00\x04\x00\x16\x00\x00\x00\xDD\x00\x00\x00\x1A\x00\x00\x00" -"\x3E\x00\x03\x00\xDC\x00\x00\x00\xDD\x00\x00\x00\x3D\x00\x04\x00\x16\x00\x00\x00\xDE\x00\x00\x00\xD5\x00\x00\x00\x3D\x00\x04\x00" -"\x16\x00\x00\x00\xDF\x00\x00\x00\xDC\x00\x00\x00\x81\x00\x05\x00\x16\x00\x00\x00\xE0\x00\x00\x00\xDF\x00\x00\x00\xDE\x00\x00\x00" -"\x3E\x00\x03\x00\xDC\x00\x00\x00\xE0\x00\x00\x00\x3D\x00\x04\x00\x16\x00\x00\x00\xE2\x00\x00\x00\xD5\x00\x00\x00\x8E\x00\x05\x00" -"\x16\x00\x00\x00\xE3\x00\x00\x00\xE2\x00\x00\x00\xE1\x00\x00\x00\x3E\x00\x03\x00\xD5\x00\x00\x00\xE3\x00\x00\x00\x3D\x00\x04\x00" -"\x16\x00\x00\x00\xE4\x00\x00\x00\xD5\x00\x00\x00\x3D\x00\x04\x00\x14\x00\x00\x00\xE5\x00\x00\x00\x19\x00\x00\x00\x3D\x00\x04\x00" -"\x16\x00\x00\x00\xE6\x00\x00\x00\xDC\x00\x00\x00\x57\x00\x05\x00\x0D\x00\x00\x00\xE7\x00\x00\x00\xE5\x00\x00\x00\xE6\x00\x00\x00" -"\x51\x00\x05\x00\x06\x00\x00\x00\xE8\x00\x00\x00\xE7\x00\x00\x00\x03\x00\x00\x00\x8E\x00\x05\x00\x16\x00\x00\x00\xE9\x00\x00\x00" -"\xE4\x00\x00\x00\xE8\x00\x00\x00\x3D\x00\x04\x00\x16\x00\x00\x00\xEA\x00\x00\x00\xDC\x00\x00\x00\x83\x00\x05\x00\x16\x00\x00\x00" -"\xEB\x00\x00\x00\xEA\x00\x00\x00\xE9\x00\x00\x00\x3E\x00\x03\x00\xDC\x00\x00\x00\xEB\x00\x00\x00\x3D\x00\x04\x00\x16\x00\x00\x00" -"\xEC\x00\x00\x00\xD5\x00\x00\x00\x3D\x00\x04\x00\x14\x00\x00\x00\xED\x00\x00\x00\x19\x00\x00\x00\x3D\x00\x04\x00\x16\x00\x00\x00" -"\xEE\x00\x00\x00\xDC\x00\x00\x00\x57\x00\x05\x00\x0D\x00\x00\x00\xEF\x00\x00\x00\xED\x00\x00\x00\xEE\x00\x00\x00\x51\x00\x05\x00" -"\x06\x00\x00\x00\xF0\x00\x00\x00\xEF\x00\x00\x00\x03\x00\x00\x00\x8E\x00\x05\x00\x16\x00\x00\x00\xF1\x00\x00\x00\xEC\x00\x00\x00" -"\xF0\x00\x00\x00\x3D\x00\x04\x00\x16\x00\x00\x00\xF2\x00\x00\x00\xDC\x00\x00\x00\x83\x00\x05\x00\x16\x00\x00\x00\xF3\x00\x00\x00" -"\xF2\x00\x00\x00\xF1\x00\x00\x00\x3E\x00\x03\x00\xDC\x00\x00\x00\xF3\x00\x00\x00\x3D\x00\x04\x00\x16\x00\x00\x00\xF4\x00\x00\x00" -"\xD5\x00\x00\x00\x3D\x00\x04\x00\x14\x00\x00\x00\xF5\x00\x00\x00\x19\x00\x00\x00\x3D\x00\x04\x00\x16\x00\x00\x00\xF6\x00\x00\x00" -"\xDC\x00\x00\x00\x57\x00\x05\x00\x0D\x00\x00\x00\xF7\x00\x00\x00\xF5\x00\x00\x00\xF6\x00\x00\x00\x51\x00\x05\x00\x06\x00\x00\x00" -"\xF8\x00\x00\x00\xF7\x00\x00\x00\x03\x00\x00\x00\x8E\x00\x05\x00\x16\x00\x00\x00\xF9\x00\x00\x00\xF4\x00\x00\x00\xF8\x00\x00\x00" -"\x3D\x00\x04\x00\x16\x00\x00\x00\xFA\x00\x00\x00\xDC\x00\x00\x00\x83\x00\x05\x00\x16\x00\x00\x00\xFB\x00\x00\x00\xFA\x00\x00\x00" -"\xF9\x00\x00\x00\x3E\x00\x03\x00\xDC\x00\x00\x00\xFB\x00\x00\x00\x3D\x00\x04\x00\x16\x00\x00\x00\xFC\x00\x00\x00\xDC\x00\x00\x00" -"\xFE\x00\x02\x00\xFC\x00\x00\x00\xF8\x00\x02\x00\xD4\x00\x00\x00\xF9\x00\x02\x00\x7E\x00\x00\x00\xF8\x00\x02\x00\x7E\x00\x00\x00" -"\x3D\x00\x04\x00\x16\x00\x00\x00\xFE\x00\x00\x00\x1A\x00\x00\x00\xFE\x00\x02\x00\xFE\x00\x00\x00\x38\x00\x01\x00"}, +"\x00\x00\x00\x00\x00\x01\x05\x46\x31\x6D\x61\x73\x6B\x00\x3F\x80\x00\x00\x01\x06\x42\x31\x6D\x61\x73\x6B\x6C\x74\x00\x00\x00\x00" +"\x00\x00\x00\x00\x03\x02\x23\x07\x00\x00\x01\x00\x06\x00\x08\x00\x8E\x00\x00\x00\x00\x00\x00\x00\x11\x00\x02\x00\x01\x00\x00\x00" +"\x0B\x00\x06\x00\x01\x00\x00\x00\x47\x4C\x53\x4C\x2E\x73\x74\x64\x2E\x34\x35\x30\x00\x00\x00\x00\x0E\x00\x03\x00\x00\x00\x00\x00" +"\x01\x00\x00\x00\x0F\x00\x12\x00\x00\x00\x00\x00\x04\x00\x00\x00\x6D\x61\x69\x6E\x00\x00\x00\x00\x1C\x00\x00\x00\x4D\x00\x00\x00" +"\x4F\x00\x00\x00\x56\x00\x00\x00\x5B\x00\x00\x00\x64\x00\x00\x00\x6E\x00\x00\x00\x70\x00\x00\x00\x72\x00\x00\x00\x73\x00\x00\x00" +"\x7A\x00\x00\x00\x7C\x00\x00\x00\x80\x00\x00\x00\x03\x00\x03\x00\x02\x00\x00\x00\xC2\x01\x00\x00\x05\x00\x04\x00\x04\x00\x00\x00" +"\x6D\x61\x69\x6E\x00\x00\x00\x00\x05\x00\x06\x00\x09\x00\x00\x00\x66\x74\x65\x74\x72\x61\x6E\x73\x66\x6F\x72\x6D\x28\x00\x00\x00" +"\x05\x00\x04\x00\x0C\x00\x00\x00\x70\x72\x6F\x6A\x00\x00\x00\x00\x05\x00\x05\x00\x13\x00\x00\x00\x65\x6E\x74\x69\x74\x79\x62\x6C" +"\x6F\x63\x6B\x00\x06\x00\x07\x00\x13\x00\x00\x00\x00\x00\x00\x00\x6D\x5F\x6D\x6F\x64\x65\x6C\x76\x69\x65\x77\x70\x72\x6F\x6A\x00" +"\x06\x00\x05\x00\x13\x00\x00\x00\x01\x00\x00\x00\x6D\x5F\x6D\x6F\x64\x65\x6C\x00\x06\x00\x06\x00\x13\x00\x00\x00\x02\x00\x00\x00" +"\x6D\x5F\x6D\x6F\x64\x65\x6C\x69\x6E\x76\x00\x00\x06\x00\x06\x00\x13\x00\x00\x00\x03\x00\x00\x00\x65\x5F\x65\x79\x65\x70\x6F\x73" +"\x00\x00\x00\x00\x06\x00\x05\x00\x13\x00\x00\x00\x04\x00\x00\x00\x65\x5F\x74\x69\x6D\x65\x00\x00\x06\x00\x07\x00\x13\x00\x00\x00" +"\x05\x00\x00\x00\x65\x5F\x6C\x69\x67\x68\x74\x5F\x61\x6D\x62\x69\x65\x6E\x74\x00\x06\x00\x05\x00\x13\x00\x00\x00\x06\x00\x00\x00" +"\x65\x70\x61\x64\x31\x00\x00\x00\x06\x00\x06\x00\x13\x00\x00\x00\x07\x00\x00\x00\x65\x5F\x6C\x69\x67\x68\x74\x5F\x64\x69\x72\x00" +"\x06\x00\x05\x00\x13\x00\x00\x00\x08\x00\x00\x00\x65\x70\x61\x64\x32\x00\x00\x00\x06\x00\x06\x00\x13\x00\x00\x00\x09\x00\x00\x00" +"\x65\x5F\x6C\x69\x67\x68\x74\x5F\x6D\x75\x6C\x00\x06\x00\x05\x00\x13\x00\x00\x00\x0A\x00\x00\x00\x65\x70\x61\x64\x33\x00\x00\x00" +"\x06\x00\x06\x00\x13\x00\x00\x00\x0B\x00\x00\x00\x65\x5F\x6C\x6D\x73\x63\x61\x6C\x65\x73\x00\x00\x06\x00\x07\x00\x13\x00\x00\x00" +"\x0C\x00\x00\x00\x65\x5F\x75\x70\x70\x65\x72\x63\x6F\x6C\x6F\x75\x72\x00\x00\x00\x06\x00\x05\x00\x13\x00\x00\x00\x0D\x00\x00\x00" +"\x65\x70\x61\x64\x34\x00\x00\x00\x06\x00\x07\x00\x13\x00\x00\x00\x0E\x00\x00\x00\x65\x5F\x6C\x6F\x77\x65\x72\x63\x6F\x6C\x6F\x75" +"\x72\x00\x00\x00\x06\x00\x05\x00\x13\x00\x00\x00\x0F\x00\x00\x00\x65\x70\x61\x64\x35\x00\x00\x00\x06\x00\x06\x00\x13\x00\x00\x00" +"\x10\x00\x00\x00\x65\x5F\x67\x6C\x6F\x77\x6D\x6F\x64\x00\x00\x00\x06\x00\x05\x00\x13\x00\x00\x00\x11\x00\x00\x00\x65\x70\x61\x64" +"\x36\x00\x00\x00\x06\x00\x07\x00\x13\x00\x00\x00\x12\x00\x00\x00\x65\x5F\x63\x6F\x6C\x6F\x75\x72\x69\x64\x65\x6E\x74\x00\x00\x00" +"\x06\x00\x07\x00\x13\x00\x00\x00\x13\x00\x00\x00\x77\x5F\x66\x6F\x67\x63\x6F\x6C\x6F\x75\x72\x73\x00\x00\x00\x00\x06\x00\x07\x00" +"\x13\x00\x00\x00\x14\x00\x00\x00\x77\x5F\x66\x6F\x67\x64\x65\x6E\x73\x69\x74\x79\x00\x00\x00\x00\x06\x00\x07\x00\x13\x00\x00\x00" +"\x15\x00\x00\x00\x77\x5F\x66\x6F\x67\x64\x65\x70\x74\x68\x62\x69\x61\x73\x00\x00\x06\x00\x05\x00\x13\x00\x00\x00\x16\x00\x00\x00" +"\x65\x70\x61\x64\x37\x00\x00\x00\x05\x00\x03\x00\x15\x00\x00\x00\x00\x00\x00\x00\x05\x00\x05\x00\x1C\x00\x00\x00\x76\x5F\x70\x6F" +"\x73\x69\x74\x69\x6F\x6E\x00\x00\x05\x00\x09\x00\x38\x00\x00\x00\x63\x76\x61\x72\x5F\x72\x5F\x67\x6C\x73\x6C\x5F\x6F\x66\x66\x73" +"\x65\x74\x6D\x61\x70\x70\x69\x6E\x67\x00\x00\x00\x05\x00\x07\x00\x3C\x00\x00\x00\x63\x76\x61\x72\x5F\x67\x6C\x5F\x73\x70\x65\x63" +"\x75\x6C\x61\x72\x00\x00\x00\x00\x05\x00\x07\x00\x3F\x00\x00\x00\x5F\x52\x45\x46\x4C\x45\x43\x54\x43\x55\x42\x45\x4D\x41\x53\x4B" +"\x00\x00\x00\x00\x05\x00\x06\x00\x45\x00\x00\x00\x65\x79\x65\x6D\x69\x6E\x75\x73\x76\x65\x72\x74\x65\x78\x00\x00\x05\x00\x05\x00" +"\x4D\x00\x00\x00\x65\x79\x65\x76\x65\x63\x74\x6F\x72\x00\x00\x00\x05\x00\x05\x00\x4F\x00\x00\x00\x76\x5F\x73\x76\x65\x63\x74\x6F" +"\x72\x00\x00\x00\x05\x00\x05\x00\x56\x00\x00\x00\x76\x5F\x74\x76\x65\x63\x74\x6F\x72\x00\x00\x00\x05\x00\x05\x00\x5B\x00\x00\x00" +"\x76\x5F\x6E\x6F\x72\x6D\x61\x6C\x00\x00\x00\x00\x05\x00\x05\x00\x64\x00\x00\x00\x69\x6E\x76\x73\x75\x72\x66\x61\x63\x65\x00\x00" +"\x05\x00\x04\x00\x6E\x00\x00\x00\x62\x61\x73\x65\x74\x63\x00\x00\x05\x00\x05\x00\x70\x00\x00\x00\x76\x5F\x74\x65\x78\x63\x6F\x6F" +"\x72\x64\x00\x00\x05\x00\x03\x00\x72\x00\x00\x00\x6C\x6D\x30\x00\x05\x00\x05\x00\x73\x00\x00\x00\x76\x5F\x6C\x6D\x63\x6F\x6F\x72" +"\x64\x00\x00\x00\x05\x00\x06\x00\x75\x00\x00\x00\x5F\x61\x72\x67\x5F\x76\x65\x72\x74\x65\x78\x6C\x69\x74\x00\x00\x05\x00\x03\x00" +"\x7A\x00\x00\x00\x76\x63\x00\x00\x05\x00\x05\x00\x7C\x00\x00\x00\x76\x5F\x63\x6F\x6C\x6F\x75\x72\x00\x00\x00\x00\x05\x00\x06\x00" +"\x7E\x00\x00\x00\x67\x6C\x5F\x50\x65\x72\x56\x65\x72\x74\x65\x78\x00\x00\x00\x00\x06\x00\x06\x00\x7E\x00\x00\x00\x00\x00\x00\x00" +"\x67\x6C\x5F\x50\x6F\x73\x69\x74\x69\x6F\x6E\x00\x05\x00\x03\x00\x80\x00\x00\x00\x00\x00\x00\x00\x05\x00\x0A\x00\x83\x00\x00\x00" +"\x63\x76\x61\x72\x5F\x72\x5F\x67\x6C\x73\x6C\x5F\x6F\x66\x66\x73\x65\x74\x6D\x61\x70\x70\x69\x6E\x67\x5F\x73\x63\x61\x6C\x65\x00" +"\x05\x00\x07\x00\x84\x00\x00\x00\x5F\x63\x76\x61\x72\x5F\x72\x5F\x66\x6F\x67\x5F\x65\x78\x70\x32\x00\x00\x00\x00\x05\x00\x05\x00" +"\x85\x00\x00\x00\x61\x72\x67\x5F\x6D\x61\x73\x6B\x00\x00\x00\x00\x05\x00\x05\x00\x86\x00\x00\x00\x5F\x61\x72\x67\x5F\x6D\x61\x73" +"\x6B\x6C\x74\x00\x05\x00\x04\x00\x87\x00\x00\x00\x5F\x42\x55\x4D\x50\x00\x00\x00\x05\x00\x05\x00\x88\x00\x00\x00\x5F\x46\x55\x4C" +"\x4C\x42\x52\x49\x47\x48\x54\x00\x05\x00\x04\x00\x89\x00\x00\x00\x5F\x46\x4F\x47\x00\x00\x00\x00\x05\x00\x05\x00\x8B\x00\x00\x00" +"\x6C\x69\x67\x68\x74\x62\x6C\x6F\x63\x6B\x00\x00\x06\x00\x07\x00\x8B\x00\x00\x00\x00\x00\x00\x00\x6C\x5F\x63\x75\x62\x65\x6D\x61" +"\x74\x72\x69\x78\x00\x00\x00\x00\x06\x00\x07\x00\x8B\x00\x00\x00\x01\x00\x00\x00\x6C\x5F\x6C\x69\x67\x68\x74\x70\x6F\x73\x69\x74" +"\x69\x6F\x6E\x00\x06\x00\x05\x00\x8B\x00\x00\x00\x02\x00\x00\x00\x6C\x70\x61\x64\x31\x00\x00\x00\x06\x00\x07\x00\x8B\x00\x00\x00" +"\x03\x00\x00\x00\x6C\x5F\x6C\x69\x67\x68\x74\x63\x6F\x6C\x6F\x75\x72\x00\x00\x00\x06\x00\x05\x00\x8B\x00\x00\x00\x04\x00\x00\x00" +"\x6C\x70\x61\x64\x32\x00\x00\x00\x06\x00\x08\x00\x8B\x00\x00\x00\x05\x00\x00\x00\x6C\x5F\x6C\x69\x67\x68\x74\x63\x6F\x6C\x6F\x75" +"\x72\x73\x63\x61\x6C\x65\x00\x00\x06\x00\x07\x00\x8B\x00\x00\x00\x06\x00\x00\x00\x6C\x5F\x6C\x69\x67\x68\x74\x72\x61\x64\x69\x75" +"\x73\x00\x00\x00\x06\x00\x07\x00\x8B\x00\x00\x00\x07\x00\x00\x00\x6C\x5F\x73\x68\x61\x64\x6F\x77\x6D\x61\x70\x70\x72\x6F\x6A\x00" +"\x06\x00\x08\x00\x8B\x00\x00\x00\x08\x00\x00\x00\x6C\x5F\x73\x68\x61\x64\x6F\x77\x6D\x61\x70\x73\x63\x61\x6C\x65\x00\x00\x00\x00" +"\x06\x00\x05\x00\x8B\x00\x00\x00\x09\x00\x00\x00\x6C\x70\x61\x64\x33\x00\x00\x00\x05\x00\x03\x00\x8D\x00\x00\x00\x00\x00\x00\x00" +"\x47\x00\x04\x00\x11\x00\x00\x00\x06\x00\x00\x00\x10\x00\x00\x00\x48\x00\x04\x00\x13\x00\x00\x00\x00\x00\x00\x00\x05\x00\x00\x00" +"\x48\x00\x05\x00\x13\x00\x00\x00\x00\x00\x00\x00\x23\x00\x00\x00\x00\x00\x00\x00\x48\x00\x05\x00\x13\x00\x00\x00\x00\x00\x00\x00" +"\x07\x00\x00\x00\x10\x00\x00\x00\x48\x00\x04\x00\x13\x00\x00\x00\x01\x00\x00\x00\x05\x00\x00\x00\x48\x00\x05\x00\x13\x00\x00\x00" +"\x01\x00\x00\x00\x23\x00\x00\x00\x40\x00\x00\x00\x48\x00\x05\x00\x13\x00\x00\x00\x01\x00\x00\x00\x07\x00\x00\x00\x10\x00\x00\x00" +"\x48\x00\x04\x00\x13\x00\x00\x00\x02\x00\x00\x00\x05\x00\x00\x00\x48\x00\x05\x00\x13\x00\x00\x00\x02\x00\x00\x00\x23\x00\x00\x00" +"\x80\x00\x00\x00\x48\x00\x05\x00\x13\x00\x00\x00\x02\x00\x00\x00\x07\x00\x00\x00\x10\x00\x00\x00\x48\x00\x05\x00\x13\x00\x00\x00" +"\x03\x00\x00\x00\x23\x00\x00\x00\xC0\x00\x00\x00\x48\x00\x05\x00\x13\x00\x00\x00\x04\x00\x00\x00\x23\x00\x00\x00\xCC\x00\x00\x00" +"\x48\x00\x05\x00\x13\x00\x00\x00\x05\x00\x00\x00\x23\x00\x00\x00\xD0\x00\x00\x00\x48\x00\x05\x00\x13\x00\x00\x00\x06\x00\x00\x00" +"\x23\x00\x00\x00\xDC\x00\x00\x00\x48\x00\x05\x00\x13\x00\x00\x00\x07\x00\x00\x00\x23\x00\x00\x00\xE0\x00\x00\x00\x48\x00\x05\x00" +"\x13\x00\x00\x00\x08\x00\x00\x00\x23\x00\x00\x00\xEC\x00\x00\x00\x48\x00\x05\x00\x13\x00\x00\x00\x09\x00\x00\x00\x23\x00\x00\x00" +"\xF0\x00\x00\x00\x48\x00\x05\x00\x13\x00\x00\x00\x0A\x00\x00\x00\x23\x00\x00\x00\xFC\x00\x00\x00\x48\x00\x05\x00\x13\x00\x00\x00" +"\x0B\x00\x00\x00\x23\x00\x00\x00\x00\x01\x00\x00\x48\x00\x05\x00\x13\x00\x00\x00\x0C\x00\x00\x00\x23\x00\x00\x00\x40\x01\x00\x00" +"\x48\x00\x05\x00\x13\x00\x00\x00\x0D\x00\x00\x00\x23\x00\x00\x00\x4C\x01\x00\x00\x48\x00\x05\x00\x13\x00\x00\x00\x0E\x00\x00\x00" +"\x23\x00\x00\x00\x50\x01\x00\x00\x48\x00\x05\x00\x13\x00\x00\x00\x0F\x00\x00\x00\x23\x00\x00\x00\x5C\x01\x00\x00\x48\x00\x05\x00" +"\x13\x00\x00\x00\x10\x00\x00\x00\x23\x00\x00\x00\x60\x01\x00\x00\x48\x00\x05\x00\x13\x00\x00\x00\x11\x00\x00\x00\x23\x00\x00\x00" +"\x6C\x01\x00\x00\x48\x00\x05\x00\x13\x00\x00\x00\x12\x00\x00\x00\x23\x00\x00\x00\x70\x01\x00\x00\x48\x00\x05\x00\x13\x00\x00\x00" +"\x13\x00\x00\x00\x23\x00\x00\x00\x80\x01\x00\x00\x48\x00\x05\x00\x13\x00\x00\x00\x14\x00\x00\x00\x23\x00\x00\x00\x90\x01\x00\x00" +"\x48\x00\x05\x00\x13\x00\x00\x00\x15\x00\x00\x00\x23\x00\x00\x00\x94\x01\x00\x00\x48\x00\x05\x00\x13\x00\x00\x00\x16\x00\x00\x00" +"\x23\x00\x00\x00\x98\x01\x00\x00\x47\x00\x03\x00\x13\x00\x00\x00\x02\x00\x00\x00\x47\x00\x04\x00\x15\x00\x00\x00\x22\x00\x00\x00" +"\x00\x00\x00\x00\x47\x00\x04\x00\x15\x00\x00\x00\x21\x00\x00\x00\x00\x00\x00\x00\x47\x00\x04\x00\x1C\x00\x00\x00\x1E\x00\x00\x00" +"\x00\x00\x00\x00\x47\x00\x04\x00\x38\x00\x00\x00\x01\x00\x00\x00\x00\x01\x00\x00\x47\x00\x04\x00\x3C\x00\x00\x00\x01\x00\x00\x00" +"\x02\x01\x00\x00\x47\x00\x04\x00\x3F\x00\x00\x00\x01\x00\x00\x00\x13\x00\x00\x00\x47\x00\x04\x00\x4D\x00\x00\x00\x1E\x00\x00\x00" +"\x01\x00\x00\x00\x47\x00\x04\x00\x4F\x00\x00\x00\x1E\x00\x00\x00\x05\x00\x00\x00\x47\x00\x04\x00\x56\x00\x00\x00\x1E\x00\x00\x00" +"\x06\x00\x00\x00\x47\x00\x04\x00\x5B\x00\x00\x00\x1E\x00\x00\x00\x04\x00\x00\x00\x47\x00\x04\x00\x64\x00\x00\x00\x1E\x00\x00\x00" +"\x04\x00\x00\x00\x47\x00\x04\x00\x6E\x00\x00\x00\x1E\x00\x00\x00\x02\x00\x00\x00\x47\x00\x04\x00\x70\x00\x00\x00\x1E\x00\x00\x00" +"\x01\x00\x00\x00\x47\x00\x04\x00\x72\x00\x00\x00\x1E\x00\x00\x00\x00\x00\x00\x00\x47\x00\x04\x00\x73\x00\x00\x00\x1E\x00\x00\x00" +"\x03\x00\x00\x00\x47\x00\x04\x00\x75\x00\x00\x00\x01\x00\x00\x00\x04\x01\x00\x00\x47\x00\x04\x00\x7A\x00\x00\x00\x1E\x00\x00\x00" +"\x03\x00\x00\x00\x47\x00\x04\x00\x7C\x00\x00\x00\x1E\x00\x00\x00\x02\x00\x00\x00\x48\x00\x05\x00\x7E\x00\x00\x00\x00\x00\x00\x00" +"\x0B\x00\x00\x00\x00\x00\x00\x00\x47\x00\x03\x00\x7E\x00\x00\x00\x02\x00\x00\x00\x47\x00\x04\x00\x83\x00\x00\x00\x01\x00\x00\x00" +"\x01\x01\x00\x00\x47\x00\x04\x00\x84\x00\x00\x00\x01\x00\x00\x00\x03\x01\x00\x00\x47\x00\x04\x00\x85\x00\x00\x00\x01\x00\x00\x00" +"\x05\x01\x00\x00\x47\x00\x04\x00\x86\x00\x00\x00\x01\x00\x00\x00\x06\x01\x00\x00\x47\x00\x04\x00\x87\x00\x00\x00\x01\x00\x00\x00" +"\x10\x00\x00\x00\x47\x00\x04\x00\x88\x00\x00\x00\x01\x00\x00\x00\x11\x00\x00\x00\x47\x00\x04\x00\x89\x00\x00\x00\x01\x00\x00\x00" +"\x15\x00\x00\x00\x48\x00\x04\x00\x8B\x00\x00\x00\x00\x00\x00\x00\x05\x00\x00\x00\x48\x00\x05\x00\x8B\x00\x00\x00\x00\x00\x00\x00" +"\x23\x00\x00\x00\x00\x00\x00\x00\x48\x00\x05\x00\x8B\x00\x00\x00\x00\x00\x00\x00\x07\x00\x00\x00\x10\x00\x00\x00\x48\x00\x05\x00" +"\x8B\x00\x00\x00\x01\x00\x00\x00\x23\x00\x00\x00\x40\x00\x00\x00\x48\x00\x05\x00\x8B\x00\x00\x00\x02\x00\x00\x00\x23\x00\x00\x00" +"\x4C\x00\x00\x00\x48\x00\x05\x00\x8B\x00\x00\x00\x03\x00\x00\x00\x23\x00\x00\x00\x50\x00\x00\x00\x48\x00\x05\x00\x8B\x00\x00\x00" +"\x04\x00\x00\x00\x23\x00\x00\x00\x5C\x00\x00\x00\x48\x00\x05\x00\x8B\x00\x00\x00\x05\x00\x00\x00\x23\x00\x00\x00\x60\x00\x00\x00" +"\x48\x00\x05\x00\x8B\x00\x00\x00\x06\x00\x00\x00\x23\x00\x00\x00\x6C\x00\x00\x00\x48\x00\x05\x00\x8B\x00\x00\x00\x07\x00\x00\x00" +"\x23\x00\x00\x00\x70\x00\x00\x00\x48\x00\x05\x00\x8B\x00\x00\x00\x08\x00\x00\x00\x23\x00\x00\x00\x80\x00\x00\x00\x48\x00\x05\x00" +"\x8B\x00\x00\x00\x09\x00\x00\x00\x23\x00\x00\x00\x88\x00\x00\x00\x47\x00\x03\x00\x8B\x00\x00\x00\x02\x00\x00\x00\x47\x00\x04\x00" +"\x8D\x00\x00\x00\x22\x00\x00\x00\x00\x00\x00\x00\x47\x00\x04\x00\x8D\x00\x00\x00\x21\x00\x00\x00\x01\x00\x00\x00\x13\x00\x02\x00" +"\x02\x00\x00\x00\x21\x00\x03\x00\x03\x00\x00\x00\x02\x00\x00\x00\x16\x00\x03\x00\x06\x00\x00\x00\x20\x00\x00\x00\x17\x00\x04\x00" +"\x07\x00\x00\x00\x06\x00\x00\x00\x04\x00\x00\x00\x21\x00\x03\x00\x08\x00\x00\x00\x07\x00\x00\x00\x20\x00\x04\x00\x0B\x00\x00\x00" +"\x07\x00\x00\x00\x07\x00\x00\x00\x18\x00\x04\x00\x0D\x00\x00\x00\x07\x00\x00\x00\x04\x00\x00\x00\x17\x00\x04\x00\x0E\x00\x00\x00" +"\x06\x00\x00\x00\x03\x00\x00\x00\x15\x00\x04\x00\x0F\x00\x00\x00\x20\x00\x00\x00\x00\x00\x00\x00\x2B\x00\x04\x00\x0F\x00\x00\x00" +"\x10\x00\x00\x00\x04\x00\x00\x00\x1C\x00\x04\x00\x11\x00\x00\x00\x07\x00\x00\x00\x10\x00\x00\x00\x17\x00\x04\x00\x12\x00\x00\x00" +"\x06\x00\x00\x00\x02\x00\x00\x00\x1E\x00\x19\x00\x13\x00\x00\x00\x0D\x00\x00\x00\x0D\x00\x00\x00\x0D\x00\x00\x00\x0E\x00\x00\x00" +"\x06\x00\x00\x00\x0E\x00\x00\x00\x06\x00\x00\x00\x0E\x00\x00\x00\x06\x00\x00\x00\x0E\x00\x00\x00\x06\x00\x00\x00\x11\x00\x00\x00" +"\x0E\x00\x00\x00\x06\x00\x00\x00\x0E\x00\x00\x00\x06\x00\x00\x00\x0E\x00\x00\x00\x06\x00\x00\x00\x07\x00\x00\x00\x07\x00\x00\x00" +"\x06\x00\x00\x00\x06\x00\x00\x00\x12\x00\x00\x00\x20\x00\x04\x00\x14\x00\x00\x00\x02\x00\x00\x00\x13\x00\x00\x00\x3B\x00\x04\x00" +"\x14\x00\x00\x00\x15\x00\x00\x00\x02\x00\x00\x00\x15\x00\x04\x00\x16\x00\x00\x00\x20\x00\x00\x00\x01\x00\x00\x00\x2B\x00\x04\x00" +"\x16\x00\x00\x00\x17\x00\x00\x00\x00\x00\x00\x00\x20\x00\x04\x00\x18\x00\x00\x00\x02\x00\x00\x00\x0D\x00\x00\x00\x20\x00\x04\x00" +"\x1B\x00\x00\x00\x01\x00\x00\x00\x0E\x00\x00\x00\x3B\x00\x04\x00\x1B\x00\x00\x00\x1C\x00\x00\x00\x01\x00\x00\x00\x2B\x00\x04\x00" +"\x06\x00\x00\x00\x1E\x00\x00\x00\x00\x00\x80\x3F\x2B\x00\x04\x00\x06\x00\x00\x00\x24\x00\x00\x00\x00\x00\x80\xBF\x2B\x00\x04\x00" +"\x0F\x00\x00\x00\x25\x00\x00\x00\x01\x00\x00\x00\x20\x00\x04\x00\x26\x00\x00\x00\x07\x00\x00\x00\x06\x00\x00\x00\x2B\x00\x04\x00" +"\x0F\x00\x00\x00\x2B\x00\x00\x00\x02\x00\x00\x00\x2B\x00\x04\x00\x0F\x00\x00\x00\x2E\x00\x00\x00\x03\x00\x00\x00\x2B\x00\x04\x00" +"\x06\x00\x00\x00\x32\x00\x00\x00\x00\x00\x00\x40\x32\x00\x04\x00\x06\x00\x00\x00\x38\x00\x00\x00\x00\x00\x80\x43\x2B\x00\x04\x00" +"\x06\x00\x00\x00\x39\x00\x00\x00\x00\x00\x00\x00\x14\x00\x02\x00\x3A\x00\x00\x00\x32\x00\x04\x00\x06\x00\x00\x00\x3C\x00\x00\x00" +"\x00\x00\x81\x43\x32\x00\x04\x00\x16\x00\x00\x00\x3F\x00\x00\x00\x13\x00\x00\x00\x34\x00\x06\x00\x3A\x00\x00\x00\x40\x00\x00\x00" +"\xAB\x00\x00\x00\x3F\x00\x00\x00\x17\x00\x00\x00\x20\x00\x04\x00\x44\x00\x00\x00\x07\x00\x00\x00\x0E\x00\x00\x00\x2B\x00\x04\x00" +"\x16\x00\x00\x00\x46\x00\x00\x00\x03\x00\x00\x00\x20\x00\x04\x00\x47\x00\x00\x00\x02\x00\x00\x00\x0E\x00\x00\x00\x20\x00\x04\x00" +"\x4C\x00\x00\x00\x03\x00\x00\x00\x0E\x00\x00\x00\x3B\x00\x04\x00\x4C\x00\x00\x00\x4D\x00\x00\x00\x03\x00\x00\x00\x3B\x00\x04\x00" +"\x1B\x00\x00\x00\x4F\x00\x00\x00\x01\x00\x00\x00\x2B\x00\x04\x00\x0F\x00\x00\x00\x52\x00\x00\x00\x00\x00\x00\x00\x20\x00\x04\x00" +"\x53\x00\x00\x00\x03\x00\x00\x00\x06\x00\x00\x00\x3B\x00\x04\x00\x1B\x00\x00\x00\x56\x00\x00\x00\x01\x00\x00\x00\x3B\x00\x04\x00" +"\x1B\x00\x00\x00\x5B\x00\x00\x00\x01\x00\x00\x00\x34\x00\x06\x00\x3A\x00\x00\x00\x5F\x00\x00\x00\xAB\x00\x00\x00\x3F\x00\x00\x00" +"\x17\x00\x00\x00\x18\x00\x04\x00\x62\x00\x00\x00\x0E\x00\x00\x00\x03\x00\x00\x00\x20\x00\x04\x00\x63\x00\x00\x00\x03\x00\x00\x00" +"\x62\x00\x00\x00\x3B\x00\x04\x00\x63\x00\x00\x00\x64\x00\x00\x00\x03\x00\x00\x00\x2B\x00\x04\x00\x16\x00\x00\x00\x67\x00\x00\x00" +"\x01\x00\x00\x00\x2B\x00\x04\x00\x16\x00\x00\x00\x6A\x00\x00\x00\x02\x00\x00\x00\x20\x00\x04\x00\x6D\x00\x00\x00\x03\x00\x00\x00" +"\x12\x00\x00\x00\x3B\x00\x04\x00\x6D\x00\x00\x00\x6E\x00\x00\x00\x03\x00\x00\x00\x20\x00\x04\x00\x6F\x00\x00\x00\x01\x00\x00\x00" +"\x12\x00\x00\x00\x3B\x00\x04\x00\x6F\x00\x00\x00\x70\x00\x00\x00\x01\x00\x00\x00\x3B\x00\x04\x00\x6D\x00\x00\x00\x72\x00\x00\x00" +"\x03\x00\x00\x00\x3B\x00\x04\x00\x6F\x00\x00\x00\x73\x00\x00\x00\x01\x00\x00\x00\x32\x00\x04\x00\x16\x00\x00\x00\x75\x00\x00\x00" +"\x04\x01\x00\x00\x34\x00\x06\x00\x3A\x00\x00\x00\x76\x00\x00\x00\xAB\x00\x00\x00\x75\x00\x00\x00\x17\x00\x00\x00\x20\x00\x04\x00" +"\x79\x00\x00\x00\x03\x00\x00\x00\x07\x00\x00\x00\x3B\x00\x04\x00\x79\x00\x00\x00\x7A\x00\x00\x00\x03\x00\x00\x00\x20\x00\x04\x00" +"\x7B\x00\x00\x00\x01\x00\x00\x00\x07\x00\x00\x00\x3B\x00\x04\x00\x7B\x00\x00\x00\x7C\x00\x00\x00\x01\x00\x00\x00\x1E\x00\x03\x00" +"\x7E\x00\x00\x00\x07\x00\x00\x00\x20\x00\x04\x00\x7F\x00\x00\x00\x03\x00\x00\x00\x7E\x00\x00\x00\x3B\x00\x04\x00\x7F\x00\x00\x00" +"\x80\x00\x00\x00\x03\x00\x00\x00\x32\x00\x04\x00\x06\x00\x00\x00\x83\x00\x00\x00\x00\x80\x80\x43\x32\x00\x04\x00\x16\x00\x00\x00" +"\x84\x00\x00\x00\x03\x01\x00\x00\x32\x00\x04\x00\x06\x00\x00\x00\x85\x00\x00\x00\x00\x80\x82\x43\x32\x00\x04\x00\x16\x00\x00\x00" +"\x86\x00\x00\x00\x06\x01\x00\x00\x32\x00\x04\x00\x16\x00\x00\x00\x87\x00\x00\x00\x10\x00\x00\x00\x32\x00\x04\x00\x16\x00\x00\x00" +"\x88\x00\x00\x00\x11\x00\x00\x00\x32\x00\x04\x00\x16\x00\x00\x00\x89\x00\x00\x00\x15\x00\x00\x00\x2A\x00\x03\x00\x3A\x00\x00\x00" +"\x8A\x00\x00\x00\x1E\x00\x0C\x00\x8B\x00\x00\x00\x0D\x00\x00\x00\x0E\x00\x00\x00\x06\x00\x00\x00\x0E\x00\x00\x00\x06\x00\x00\x00" +"\x0E\x00\x00\x00\x06\x00\x00\x00\x07\x00\x00\x00\x12\x00\x00\x00\x12\x00\x00\x00\x20\x00\x04\x00\x8C\x00\x00\x00\x02\x00\x00\x00" +"\x8B\x00\x00\x00\x3B\x00\x04\x00\x8C\x00\x00\x00\x8D\x00\x00\x00\x02\x00\x00\x00\x36\x00\x05\x00\x02\x00\x00\x00\x04\x00\x00\x00" +"\x00\x00\x00\x00\x03\x00\x00\x00\xF8\x00\x02\x00\x05\x00\x00\x00\x3B\x00\x04\x00\x44\x00\x00\x00\x45\x00\x00\x00\x07\x00\x00\x00" +"\xBA\x00\x05\x00\x3A\x00\x00\x00\x3B\x00\x00\x00\x38\x00\x00\x00\x39\x00\x00\x00\xBA\x00\x05\x00\x3A\x00\x00\x00\x3D\x00\x00\x00" +"\x3C\x00\x00\x00\x39\x00\x00\x00\xA6\x00\x05\x00\x3A\x00\x00\x00\x3E\x00\x00\x00\x3B\x00\x00\x00\x3D\x00\x00\x00\xA6\x00\x05\x00" +"\x3A\x00\x00\x00\x41\x00\x00\x00\x3E\x00\x00\x00\x40\x00\x00\x00\xF7\x00\x03\x00\x43\x00\x00\x00\x00\x00\x00\x00\xFA\x00\x04\x00" +"\x41\x00\x00\x00\x42\x00\x00\x00\x43\x00\x00\x00\xF8\x00\x02\x00\x42\x00\x00\x00\x41\x00\x05\x00\x47\x00\x00\x00\x48\x00\x00\x00" +"\x15\x00\x00\x00\x46\x00\x00\x00\x3D\x00\x04\x00\x0E\x00\x00\x00\x49\x00\x00\x00\x48\x00\x00\x00\x3D\x00\x04\x00\x0E\x00\x00\x00" +"\x4A\x00\x00\x00\x1C\x00\x00\x00\x83\x00\x05\x00\x0E\x00\x00\x00\x4B\x00\x00\x00\x49\x00\x00\x00\x4A\x00\x00\x00\x3E\x00\x03\x00" +"\x45\x00\x00\x00\x4B\x00\x00\x00\x3D\x00\x04\x00\x0E\x00\x00\x00\x4E\x00\x00\x00\x45\x00\x00\x00\x3D\x00\x04\x00\x0E\x00\x00\x00" +"\x50\x00\x00\x00\x4F\x00\x00\x00\x94\x00\x05\x00\x06\x00\x00\x00\x51\x00\x00\x00\x4E\x00\x00\x00\x50\x00\x00\x00\x41\x00\x05\x00" +"\x53\x00\x00\x00\x54\x00\x00\x00\x4D\x00\x00\x00\x52\x00\x00\x00\x3E\x00\x03\x00\x54\x00\x00\x00\x51\x00\x00\x00\x3D\x00\x04\x00" +"\x0E\x00\x00\x00\x55\x00\x00\x00\x45\x00\x00\x00\x3D\x00\x04\x00\x0E\x00\x00\x00\x57\x00\x00\x00\x56\x00\x00\x00\x94\x00\x05\x00" +"\x06\x00\x00\x00\x58\x00\x00\x00\x55\x00\x00\x00\x57\x00\x00\x00\x41\x00\x05\x00\x53\x00\x00\x00\x59\x00\x00\x00\x4D\x00\x00\x00" +"\x25\x00\x00\x00\x3E\x00\x03\x00\x59\x00\x00\x00\x58\x00\x00\x00\x3D\x00\x04\x00\x0E\x00\x00\x00\x5A\x00\x00\x00\x45\x00\x00\x00" +"\x3D\x00\x04\x00\x0E\x00\x00\x00\x5C\x00\x00\x00\x5B\x00\x00\x00\x94\x00\x05\x00\x06\x00\x00\x00\x5D\x00\x00\x00\x5A\x00\x00\x00" +"\x5C\x00\x00\x00\x41\x00\x05\x00\x53\x00\x00\x00\x5E\x00\x00\x00\x4D\x00\x00\x00\x2B\x00\x00\x00\x3E\x00\x03\x00\x5E\x00\x00\x00" +"\x5D\x00\x00\x00\xF9\x00\x02\x00\x43\x00\x00\x00\xF8\x00\x02\x00\x43\x00\x00\x00\xF7\x00\x03\x00\x61\x00\x00\x00\x00\x00\x00\x00" +"\xFA\x00\x04\x00\x5F\x00\x00\x00\x60\x00\x00\x00\x61\x00\x00\x00\xF8\x00\x02\x00\x60\x00\x00\x00\x3D\x00\x04\x00\x0E\x00\x00\x00" +"\x65\x00\x00\x00\x4F\x00\x00\x00\x41\x00\x05\x00\x4C\x00\x00\x00\x66\x00\x00\x00\x64\x00\x00\x00\x17\x00\x00\x00\x3E\x00\x03\x00" +"\x66\x00\x00\x00\x65\x00\x00\x00\x3D\x00\x04\x00\x0E\x00\x00\x00\x68\x00\x00\x00\x56\x00\x00\x00\x41\x00\x05\x00\x4C\x00\x00\x00" +"\x69\x00\x00\x00\x64\x00\x00\x00\x67\x00\x00\x00\x3E\x00\x03\x00\x69\x00\x00\x00\x68\x00\x00\x00\x3D\x00\x04\x00\x0E\x00\x00\x00" +"\x6B\x00\x00\x00\x5B\x00\x00\x00\x41\x00\x05\x00\x4C\x00\x00\x00\x6C\x00\x00\x00\x64\x00\x00\x00\x6A\x00\x00\x00\x3E\x00\x03\x00" +"\x6C\x00\x00\x00\x6B\x00\x00\x00\xF9\x00\x02\x00\x61\x00\x00\x00\xF8\x00\x02\x00\x61\x00\x00\x00\x3D\x00\x04\x00\x12\x00\x00\x00" +"\x71\x00\x00\x00\x70\x00\x00\x00\x3E\x00\x03\x00\x6E\x00\x00\x00\x71\x00\x00\x00\x3D\x00\x04\x00\x12\x00\x00\x00\x74\x00\x00\x00" +"\x73\x00\x00\x00\x3E\x00\x03\x00\x72\x00\x00\x00\x74\x00\x00\x00\xF7\x00\x03\x00\x78\x00\x00\x00\x00\x00\x00\x00\xFA\x00\x04\x00" +"\x76\x00\x00\x00\x77\x00\x00\x00\x78\x00\x00\x00\xF8\x00\x02\x00\x77\x00\x00\x00\x3D\x00\x04\x00\x07\x00\x00\x00\x7D\x00\x00\x00" +"\x7C\x00\x00\x00\x3E\x00\x03\x00\x7A\x00\x00\x00\x7D\x00\x00\x00\xF9\x00\x02\x00\x78\x00\x00\x00\xF8\x00\x02\x00\x78\x00\x00\x00" +"\x39\x00\x04\x00\x07\x00\x00\x00\x81\x00\x00\x00\x09\x00\x00\x00\x41\x00\x05\x00\x79\x00\x00\x00\x82\x00\x00\x00\x80\x00\x00\x00" +"\x17\x00\x00\x00\x3E\x00\x03\x00\x82\x00\x00\x00\x81\x00\x00\x00\xFD\x00\x01\x00\x38\x00\x01\x00\x36\x00\x05\x00\x07\x00\x00\x00" +"\x09\x00\x00\x00\x00\x00\x00\x00\x08\x00\x00\x00\xF8\x00\x02\x00\x0A\x00\x00\x00\x3B\x00\x04\x00\x0B\x00\x00\x00\x0C\x00\x00\x00" +"\x07\x00\x00\x00\x41\x00\x05\x00\x18\x00\x00\x00\x19\x00\x00\x00\x15\x00\x00\x00\x17\x00\x00\x00\x3D\x00\x04\x00\x0D\x00\x00\x00" +"\x1A\x00\x00\x00\x19\x00\x00\x00\x3D\x00\x04\x00\x0E\x00\x00\x00\x1D\x00\x00\x00\x1C\x00\x00\x00\x51\x00\x05\x00\x06\x00\x00\x00" +"\x1F\x00\x00\x00\x1D\x00\x00\x00\x00\x00\x00\x00\x51\x00\x05\x00\x06\x00\x00\x00\x20\x00\x00\x00\x1D\x00\x00\x00\x01\x00\x00\x00" +"\x51\x00\x05\x00\x06\x00\x00\x00\x21\x00\x00\x00\x1D\x00\x00\x00\x02\x00\x00\x00\x50\x00\x07\x00\x07\x00\x00\x00\x22\x00\x00\x00" +"\x1F\x00\x00\x00\x20\x00\x00\x00\x21\x00\x00\x00\x1E\x00\x00\x00\x91\x00\x05\x00\x07\x00\x00\x00\x23\x00\x00\x00\x1A\x00\x00\x00" +"\x22\x00\x00\x00\x3E\x00\x03\x00\x0C\x00\x00\x00\x23\x00\x00\x00\x41\x00\x05\x00\x26\x00\x00\x00\x27\x00\x00\x00\x0C\x00\x00\x00" +"\x25\x00\x00\x00\x3D\x00\x04\x00\x06\x00\x00\x00\x28\x00\x00\x00\x27\x00\x00\x00\x85\x00\x05\x00\x06\x00\x00\x00\x29\x00\x00\x00" +"\x28\x00\x00\x00\x24\x00\x00\x00\x41\x00\x05\x00\x26\x00\x00\x00\x2A\x00\x00\x00\x0C\x00\x00\x00\x25\x00\x00\x00\x3E\x00\x03\x00" +"\x2A\x00\x00\x00\x29\x00\x00\x00\x41\x00\x05\x00\x26\x00\x00\x00\x2C\x00\x00\x00\x0C\x00\x00\x00\x2B\x00\x00\x00\x3D\x00\x04\x00" +"\x06\x00\x00\x00\x2D\x00\x00\x00\x2C\x00\x00\x00\x41\x00\x05\x00\x26\x00\x00\x00\x2F\x00\x00\x00\x0C\x00\x00\x00\x2E\x00\x00\x00" +"\x3D\x00\x04\x00\x06\x00\x00\x00\x30\x00\x00\x00\x2F\x00\x00\x00\x81\x00\x05\x00\x06\x00\x00\x00\x31\x00\x00\x00\x2D\x00\x00\x00" +"\x30\x00\x00\x00\x88\x00\x05\x00\x06\x00\x00\x00\x33\x00\x00\x00\x31\x00\x00\x00\x32\x00\x00\x00\x41\x00\x05\x00\x26\x00\x00\x00" +"\x34\x00\x00\x00\x0C\x00\x00\x00\x2B\x00\x00\x00\x3E\x00\x03\x00\x34\x00\x00\x00\x33\x00\x00\x00\x3D\x00\x04\x00\x07\x00\x00\x00" +"\x35\x00\x00\x00\x0C\x00\x00\x00\xFE\x00\x02\x00\x35\x00\x00\x00\x38\x00\x01\x00\x03\x02\x23\x07\x00\x00\x01\x00\x06\x00\x08\x00" +"\x05\x02\x00\x00\x00\x00\x00\x00\x11\x00\x02\x00\x01\x00\x00\x00\x0B\x00\x06\x00\x01\x00\x00\x00\x47\x4C\x53\x4C\x2E\x73\x74\x64" +"\x2E\x34\x35\x30\x00\x00\x00\x00\x0E\x00\x03\x00\x00\x00\x00\x00\x01\x00\x00\x00\x0F\x00\x0C\x00\x04\x00\x00\x00\x04\x00\x00\x00" +"\x6D\x61\x69\x6E\x00\x00\x00\x00\x36\x00\x00\x00\x03\x01\x00\x00\x0A\x01\x00\x00\x11\x01\x00\x00\x38\x01\x00\x00\x43\x01\x00\x00" +"\x9F\x01\x00\x00\x10\x00\x03\x00\x04\x00\x00\x00\x07\x00\x00\x00\x03\x00\x03\x00\x02\x00\x00\x00\xC2\x01\x00\x00\x05\x00\x04\x00" +"\x04\x00\x00\x00\x6D\x61\x69\x6E\x00\x00\x00\x00\x05\x00\x05\x00\x0B\x00\x00\x00\x66\x6F\x67\x33\x28\x76\x66\x33\x3B\x00\x00\x00" +"\x05\x00\x06\x00\x0A\x00\x00\x00\x72\x65\x67\x75\x6C\x61\x72\x63\x6F\x6C\x6F\x75\x72\x00\x00\x00\x05\x00\x05\x00\x11\x00\x00\x00" +"\x66\x6F\x67\x34\x28\x76\x66\x34\x3B\x00\x00\x00\x05\x00\x06\x00\x10\x00\x00\x00\x72\x65\x67\x75\x6C\x61\x72\x63\x6F\x6C\x6F\x75" +"\x72\x00\x00\x00\x05\x00\x08\x00\x1C\x00\x00\x00\x6F\x66\x66\x73\x65\x74\x6D\x61\x70\x28\x73\x32\x31\x3B\x76\x66\x32\x3B\x76\x66" +"\x33\x3B\x00\x00\x05\x00\x04\x00\x19\x00\x00\x00\x6E\x6F\x72\x6D\x74\x65\x78\x00\x05\x00\x04\x00\x1A\x00\x00\x00\x62\x61\x73\x65" +"\x00\x00\x00\x00\x05\x00\x05\x00\x1B\x00\x00\x00\x65\x79\x65\x76\x65\x63\x74\x6F\x72\x00\x00\x00\x05\x00\x04\x00\x1F\x00\x00\x00" +"\x5F\x46\x4F\x47\x00\x00\x00\x00\x05\x00\x03\x00\x29\x00\x00\x00\x7A\x00\x00\x00\x05\x00\x05\x00\x2E\x00\x00\x00\x65\x6E\x74\x69" +"\x74\x79\x62\x6C\x6F\x63\x6B\x00\x06\x00\x07\x00\x2E\x00\x00\x00\x00\x00\x00\x00\x6D\x5F\x6D\x6F\x64\x65\x6C\x76\x69\x65\x77\x70" +"\x72\x6F\x6A\x00\x06\x00\x05\x00\x2E\x00\x00\x00\x01\x00\x00\x00\x6D\x5F\x6D\x6F\x64\x65\x6C\x00\x06\x00\x06\x00\x2E\x00\x00\x00" +"\x02\x00\x00\x00\x6D\x5F\x6D\x6F\x64\x65\x6C\x69\x6E\x76\x00\x00\x06\x00\x06\x00\x2E\x00\x00\x00\x03\x00\x00\x00\x65\x5F\x65\x79" +"\x65\x70\x6F\x73\x00\x00\x00\x00\x06\x00\x05\x00\x2E\x00\x00\x00\x04\x00\x00\x00\x65\x5F\x74\x69\x6D\x65\x00\x00\x06\x00\x07\x00" +"\x2E\x00\x00\x00\x05\x00\x00\x00\x65\x5F\x6C\x69\x67\x68\x74\x5F\x61\x6D\x62\x69\x65\x6E\x74\x00\x06\x00\x05\x00\x2E\x00\x00\x00" +"\x06\x00\x00\x00\x65\x70\x61\x64\x31\x00\x00\x00\x06\x00\x06\x00\x2E\x00\x00\x00\x07\x00\x00\x00\x65\x5F\x6C\x69\x67\x68\x74\x5F" +"\x64\x69\x72\x00\x06\x00\x05\x00\x2E\x00\x00\x00\x08\x00\x00\x00\x65\x70\x61\x64\x32\x00\x00\x00\x06\x00\x06\x00\x2E\x00\x00\x00" +"\x09\x00\x00\x00\x65\x5F\x6C\x69\x67\x68\x74\x5F\x6D\x75\x6C\x00\x06\x00\x05\x00\x2E\x00\x00\x00\x0A\x00\x00\x00\x65\x70\x61\x64" +"\x33\x00\x00\x00\x06\x00\x06\x00\x2E\x00\x00\x00\x0B\x00\x00\x00\x65\x5F\x6C\x6D\x73\x63\x61\x6C\x65\x73\x00\x00\x06\x00\x07\x00" +"\x2E\x00\x00\x00\x0C\x00\x00\x00\x65\x5F\x75\x70\x70\x65\x72\x63\x6F\x6C\x6F\x75\x72\x00\x00\x00\x06\x00\x05\x00\x2E\x00\x00\x00" +"\x0D\x00\x00\x00\x65\x70\x61\x64\x34\x00\x00\x00\x06\x00\x07\x00\x2E\x00\x00\x00\x0E\x00\x00\x00\x65\x5F\x6C\x6F\x77\x65\x72\x63" +"\x6F\x6C\x6F\x75\x72\x00\x00\x00\x06\x00\x05\x00\x2E\x00\x00\x00\x0F\x00\x00\x00\x65\x70\x61\x64\x35\x00\x00\x00\x06\x00\x06\x00" +"\x2E\x00\x00\x00\x10\x00\x00\x00\x65\x5F\x67\x6C\x6F\x77\x6D\x6F\x64\x00\x00\x00\x06\x00\x05\x00\x2E\x00\x00\x00\x11\x00\x00\x00" +"\x65\x70\x61\x64\x36\x00\x00\x00\x06\x00\x07\x00\x2E\x00\x00\x00\x12\x00\x00\x00\x65\x5F\x63\x6F\x6C\x6F\x75\x72\x69\x64\x65\x6E" +"\x74\x00\x00\x00\x06\x00\x07\x00\x2E\x00\x00\x00\x13\x00\x00\x00\x77\x5F\x66\x6F\x67\x63\x6F\x6C\x6F\x75\x72\x73\x00\x00\x00\x00" +"\x06\x00\x07\x00\x2E\x00\x00\x00\x14\x00\x00\x00\x77\x5F\x66\x6F\x67\x64\x65\x6E\x73\x69\x74\x79\x00\x00\x00\x00\x06\x00\x07\x00" +"\x2E\x00\x00\x00\x15\x00\x00\x00\x77\x5F\x66\x6F\x67\x64\x65\x70\x74\x68\x62\x69\x61\x73\x00\x00\x06\x00\x05\x00\x2E\x00\x00\x00" +"\x16\x00\x00\x00\x65\x70\x61\x64\x37\x00\x00\x00\x05\x00\x03\x00\x30\x00\x00\x00\x00\x00\x00\x00\x05\x00\x06\x00\x36\x00\x00\x00" +"\x67\x6C\x5F\x46\x72\x61\x67\x43\x6F\x6F\x72\x64\x00\x00\x00\x00\x05\x00\x07\x00\x47\x00\x00\x00\x5F\x63\x76\x61\x72\x5F\x72\x5F" +"\x66\x6F\x67\x5F\x65\x78\x70\x32\x00\x00\x00\x00\x05\x00\x03\x00\x4E\x00\x00\x00\x66\x61\x63\x00\x05\x00\x04\x00\x6F\x00\x00\x00" +"\x70\x61\x72\x61\x6D\x00\x00\x00\x05\x00\x06\x00\x7F\x00\x00\x00\x4F\x66\x66\x73\x65\x74\x56\x65\x63\x74\x6F\x72\x00\x00\x00\x00" +"\x05\x00\x0A\x00\x83\x00\x00\x00\x63\x76\x61\x72\x5F\x72\x5F\x67\x6C\x73\x6C\x5F\x6F\x66\x66\x73\x65\x74\x6D\x61\x70\x70\x69\x6E" +"\x67\x5F\x73\x63\x61\x6C\x65\x00\x05\x00\x03\x00\x8C\x00\x00\x00\x52\x54\x00\x00\x05\x00\x03\x00\x98\x00\x00\x00\x69\x00\x00\x00" +"\x05\x00\x03\x00\xAE\x00\x00\x00\x66\x00\x00\x00\x05\x00\x09\x00\xD1\x00\x00\x00\x63\x76\x61\x72\x5F\x72\x5F\x67\x6C\x73\x6C\x5F" +"\x6F\x66\x66\x73\x65\x74\x6D\x61\x70\x70\x69\x6E\x67\x00\x00\x00\x05\x00\x06\x00\xD5\x00\x00\x00\x4F\x66\x66\x73\x65\x74\x56\x65" +"\x63\x74\x6F\x72\x00\x00\x00\x00\x05\x00\x03\x00\xDC\x00\x00\x00\x74\x63\x00\x00\x05\x00\x03\x00\x01\x01\x00\x00\x74\x63\x00\x00" +"\x05\x00\x04\x00\x03\x01\x00\x00\x62\x61\x73\x65\x74\x63\x00\x00\x05\x00\x05\x00\x08\x01\x00\x00\x73\x5F\x6E\x6F\x72\x6D\x61\x6C" +"\x6D\x61\x70\x00\x05\x00\x05\x00\x0A\x01\x00\x00\x65\x79\x65\x76\x65\x63\x74\x6F\x72\x00\x00\x00\x05\x00\x04\x00\x0B\x01\x00\x00" +"\x70\x61\x72\x61\x6D\x00\x00\x00\x05\x00\x04\x00\x0D\x01\x00\x00\x70\x61\x72\x61\x6D\x00\x00\x00\x05\x00\x05\x00\x11\x01\x00\x00" +"\x6F\x75\x74\x63\x6F\x6C\x6F\x75\x72\x00\x00\x00\x05\x00\x05\x00\x12\x01\x00\x00\x73\x5F\x64\x69\x66\x66\x75\x73\x65\x00\x00\x00" +"\x05\x00\x04\x00\x16\x01\x00\x00\x5F\x42\x55\x4D\x50\x00\x00\x00\x05\x00\x07\x00\x1A\x01\x00\x00\x63\x76\x61\x72\x5F\x67\x6C\x5F" +"\x73\x70\x65\x63\x75\x6C\x61\x72\x00\x00\x00\x00\x05\x00\x07\x00\x1D\x01\x00\x00\x5F\x52\x45\x46\x4C\x45\x43\x54\x43\x55\x42\x45" +"\x4D\x41\x53\x4B\x00\x00\x00\x00\x05\x00\x04\x00\x23\x01\x00\x00\x6E\x6F\x72\x6D\x00\x00\x00\x00\x05\x00\x06\x00\x33\x01\x00\x00" +"\x5F\x61\x72\x67\x5F\x76\x65\x72\x74\x65\x78\x6C\x69\x74\x00\x00\x05\x00\x05\x00\x37\x01\x00\x00\x6C\x69\x67\x68\x74\x6D\x61\x70" +"\x73\x00\x00\x00\x05\x00\x03\x00\x38\x01\x00\x00\x76\x63\x00\x00\x05\x00\x05\x00\x41\x01\x00\x00\x73\x5F\x6C\x69\x67\x68\x74\x6D" +"\x61\x70\x00\x00\x05\x00\x03\x00\x43\x01\x00\x00\x6C\x6D\x30\x00\x05\x00\x04\x00\x4C\x01\x00\x00\x64\x65\x6C\x75\x78\x00\x00\x00" +"\x05\x00\x05\x00\x4E\x01\x00\x00\x73\x5F\x64\x65\x6C\x75\x78\x6D\x61\x70\x00\x00\x05\x00\x04\x00\x65\x01\x00\x00\x73\x70\x65\x63" +"\x73\x00\x00\x00\x05\x00\x05\x00\x66\x01\x00\x00\x73\x5F\x73\x70\x65\x63\x75\x6C\x61\x72\x00\x00\x05\x00\x04\x00\x6C\x01\x00\x00" +"\x68\x61\x6C\x66\x64\x69\x72\x00\x05\x00\x04\x00\x7D\x01\x00\x00\x73\x70\x65\x63\x00\x00\x00\x00\x05\x00\x03\x00\x95\x01\x00\x00" +"\x72\x74\x63\x00\x05\x00\x05\x00\x9F\x01\x00\x00\x69\x6E\x76\x73\x75\x72\x66\x61\x63\x65\x00\x00\x05\x00\x06\x00\xBC\x01\x00\x00" +"\x73\x5F\x72\x65\x66\x6C\x65\x63\x74\x6D\x61\x73\x6B\x00\x00\x00\x05\x00\x06\x00\xC4\x01\x00\x00\x73\x5F\x72\x65\x66\x6C\x65\x63" +"\x74\x63\x75\x62\x65\x00\x00\x00\x05\x00\x05\x00\xD5\x01\x00\x00\x5F\x46\x55\x4C\x4C\x42\x52\x49\x47\x48\x54\x00\x05\x00\x06\x00" +"\xD9\x01\x00\x00\x73\x5F\x66\x75\x6C\x6C\x62\x72\x69\x67\x68\x74\x00\x00\x00\x00\x05\x00\x05\x00\xE8\x01\x00\x00\x61\x72\x67\x5F" +"\x6D\x61\x73\x6B\x00\x00\x00\x00\x05\x00\x05\x00\xEC\x01\x00\x00\x5F\x61\x72\x67\x5F\x6D\x61\x73\x6B\x6C\x74\x00\x05\x00\x04\x00" +"\xFF\x01\x00\x00\x70\x61\x72\x61\x6D\x00\x00\x00\x05\x00\x05\x00\x02\x02\x00\x00\x6C\x69\x67\x68\x74\x62\x6C\x6F\x63\x6B\x00\x00" +"\x06\x00\x07\x00\x02\x02\x00\x00\x00\x00\x00\x00\x6C\x5F\x63\x75\x62\x65\x6D\x61\x74\x72\x69\x78\x00\x00\x00\x00\x06\x00\x07\x00" +"\x02\x02\x00\x00\x01\x00\x00\x00\x6C\x5F\x6C\x69\x67\x68\x74\x70\x6F\x73\x69\x74\x69\x6F\x6E\x00\x06\x00\x05\x00\x02\x02\x00\x00" +"\x02\x00\x00\x00\x6C\x70\x61\x64\x31\x00\x00\x00\x06\x00\x07\x00\x02\x02\x00\x00\x03\x00\x00\x00\x6C\x5F\x6C\x69\x67\x68\x74\x63" +"\x6F\x6C\x6F\x75\x72\x00\x00\x00\x06\x00\x05\x00\x02\x02\x00\x00\x04\x00\x00\x00\x6C\x70\x61\x64\x32\x00\x00\x00\x06\x00\x08\x00" +"\x02\x02\x00\x00\x05\x00\x00\x00\x6C\x5F\x6C\x69\x67\x68\x74\x63\x6F\x6C\x6F\x75\x72\x73\x63\x61\x6C\x65\x00\x00\x06\x00\x07\x00" +"\x02\x02\x00\x00\x06\x00\x00\x00\x6C\x5F\x6C\x69\x67\x68\x74\x72\x61\x64\x69\x75\x73\x00\x00\x00\x06\x00\x07\x00\x02\x02\x00\x00" +"\x07\x00\x00\x00\x6C\x5F\x73\x68\x61\x64\x6F\x77\x6D\x61\x70\x70\x72\x6F\x6A\x00\x06\x00\x08\x00\x02\x02\x00\x00\x08\x00\x00\x00" +"\x6C\x5F\x73\x68\x61\x64\x6F\x77\x6D\x61\x70\x73\x63\x61\x6C\x65\x00\x00\x00\x00\x06\x00\x05\x00\x02\x02\x00\x00\x09\x00\x00\x00" +"\x6C\x70\x61\x64\x33\x00\x00\x00\x05\x00\x03\x00\x04\x02\x00\x00\x00\x00\x00\x00\x47\x00\x04\x00\x1F\x00\x00\x00\x01\x00\x00\x00" +"\x15\x00\x00\x00\x47\x00\x04\x00\x2D\x00\x00\x00\x06\x00\x00\x00\x10\x00\x00\x00\x48\x00\x04\x00\x2E\x00\x00\x00\x00\x00\x00\x00" +"\x05\x00\x00\x00\x48\x00\x05\x00\x2E\x00\x00\x00\x00\x00\x00\x00\x23\x00\x00\x00\x00\x00\x00\x00\x48\x00\x05\x00\x2E\x00\x00\x00" +"\x00\x00\x00\x00\x07\x00\x00\x00\x10\x00\x00\x00\x48\x00\x04\x00\x2E\x00\x00\x00\x01\x00\x00\x00\x05\x00\x00\x00\x48\x00\x05\x00" +"\x2E\x00\x00\x00\x01\x00\x00\x00\x23\x00\x00\x00\x40\x00\x00\x00\x48\x00\x05\x00\x2E\x00\x00\x00\x01\x00\x00\x00\x07\x00\x00\x00" +"\x10\x00\x00\x00\x48\x00\x04\x00\x2E\x00\x00\x00\x02\x00\x00\x00\x05\x00\x00\x00\x48\x00\x05\x00\x2E\x00\x00\x00\x02\x00\x00\x00" +"\x23\x00\x00\x00\x80\x00\x00\x00\x48\x00\x05\x00\x2E\x00\x00\x00\x02\x00\x00\x00\x07\x00\x00\x00\x10\x00\x00\x00\x48\x00\x05\x00" +"\x2E\x00\x00\x00\x03\x00\x00\x00\x23\x00\x00\x00\xC0\x00\x00\x00\x48\x00\x05\x00\x2E\x00\x00\x00\x04\x00\x00\x00\x23\x00\x00\x00" +"\xCC\x00\x00\x00\x48\x00\x05\x00\x2E\x00\x00\x00\x05\x00\x00\x00\x23\x00\x00\x00\xD0\x00\x00\x00\x48\x00\x05\x00\x2E\x00\x00\x00" +"\x06\x00\x00\x00\x23\x00\x00\x00\xDC\x00\x00\x00\x48\x00\x05\x00\x2E\x00\x00\x00\x07\x00\x00\x00\x23\x00\x00\x00\xE0\x00\x00\x00" +"\x48\x00\x05\x00\x2E\x00\x00\x00\x08\x00\x00\x00\x23\x00\x00\x00\xEC\x00\x00\x00\x48\x00\x05\x00\x2E\x00\x00\x00\x09\x00\x00\x00" +"\x23\x00\x00\x00\xF0\x00\x00\x00\x48\x00\x05\x00\x2E\x00\x00\x00\x0A\x00\x00\x00\x23\x00\x00\x00\xFC\x00\x00\x00\x48\x00\x05\x00" +"\x2E\x00\x00\x00\x0B\x00\x00\x00\x23\x00\x00\x00\x00\x01\x00\x00\x48\x00\x05\x00\x2E\x00\x00\x00\x0C\x00\x00\x00\x23\x00\x00\x00" +"\x40\x01\x00\x00\x48\x00\x05\x00\x2E\x00\x00\x00\x0D\x00\x00\x00\x23\x00\x00\x00\x4C\x01\x00\x00\x48\x00\x05\x00\x2E\x00\x00\x00" +"\x0E\x00\x00\x00\x23\x00\x00\x00\x50\x01\x00\x00\x48\x00\x05\x00\x2E\x00\x00\x00\x0F\x00\x00\x00\x23\x00\x00\x00\x5C\x01\x00\x00" +"\x48\x00\x05\x00\x2E\x00\x00\x00\x10\x00\x00\x00\x23\x00\x00\x00\x60\x01\x00\x00\x48\x00\x05\x00\x2E\x00\x00\x00\x11\x00\x00\x00" +"\x23\x00\x00\x00\x6C\x01\x00\x00\x48\x00\x05\x00\x2E\x00\x00\x00\x12\x00\x00\x00\x23\x00\x00\x00\x70\x01\x00\x00\x48\x00\x05\x00" +"\x2E\x00\x00\x00\x13\x00\x00\x00\x23\x00\x00\x00\x80\x01\x00\x00\x48\x00\x05\x00\x2E\x00\x00\x00\x14\x00\x00\x00\x23\x00\x00\x00" +"\x90\x01\x00\x00\x48\x00\x05\x00\x2E\x00\x00\x00\x15\x00\x00\x00\x23\x00\x00\x00\x94\x01\x00\x00\x48\x00\x05\x00\x2E\x00\x00\x00" +"\x16\x00\x00\x00\x23\x00\x00\x00\x98\x01\x00\x00\x47\x00\x03\x00\x2E\x00\x00\x00\x02\x00\x00\x00\x47\x00\x04\x00\x30\x00\x00\x00" +"\x22\x00\x00\x00\x00\x00\x00\x00\x47\x00\x04\x00\x30\x00\x00\x00\x21\x00\x00\x00\x00\x00\x00\x00\x47\x00\x04\x00\x36\x00\x00\x00" +"\x0B\x00\x00\x00\x0F\x00\x00\x00\x47\x00\x04\x00\x47\x00\x00\x00\x01\x00\x00\x00\x03\x01\x00\x00\x47\x00\x04\x00\x83\x00\x00\x00" +"\x01\x00\x00\x00\x01\x01\x00\x00\x47\x00\x04\x00\xD1\x00\x00\x00\x01\x00\x00\x00\x00\x01\x00\x00\x47\x00\x04\x00\x03\x01\x00\x00" +"\x1E\x00\x00\x00\x02\x00\x00\x00\x47\x00\x04\x00\x08\x01\x00\x00\x22\x00\x00\x00\x00\x00\x00\x00\x47\x00\x04\x00\x08\x01\x00\x00" +"\x21\x00\x00\x00\x03\x00\x00\x00\x47\x00\x04\x00\x0A\x01\x00\x00\x1E\x00\x00\x00\x01\x00\x00\x00\x47\x00\x04\x00\x11\x01\x00\x00" +"\x1E\x00\x00\x00\x00\x00\x00\x00\x47\x00\x04\x00\x12\x01\x00\x00\x22\x00\x00\x00\x00\x00\x00\x00\x47\x00\x04\x00\x12\x01\x00\x00" +"\x21\x00\x00\x00\x02\x00\x00\x00\x47\x00\x04\x00\x16\x01\x00\x00\x01\x00\x00\x00\x10\x00\x00\x00\x47\x00\x04\x00\x1A\x01\x00\x00" +"\x01\x00\x00\x00\x02\x01\x00\x00\x47\x00\x04\x00\x1D\x01\x00\x00\x01\x00\x00\x00\x13\x00\x00\x00\x47\x00\x04\x00\x33\x01\x00\x00" +"\x01\x00\x00\x00\x04\x01\x00\x00\x47\x00\x04\x00\x38\x01\x00\x00\x1E\x00\x00\x00\x03\x00\x00\x00\x47\x00\x04\x00\x41\x01\x00\x00" +"\x22\x00\x00\x00\x00\x00\x00\x00\x47\x00\x04\x00\x41\x01\x00\x00\x21\x00\x00\x00\x08\x00\x00\x00\x47\x00\x04\x00\x43\x01\x00\x00" +"\x1E\x00\x00\x00\x00\x00\x00\x00\x47\x00\x04\x00\x4E\x01\x00\x00\x22\x00\x00\x00\x00\x00\x00\x00\x47\x00\x04\x00\x4E\x01\x00\x00" +"\x21\x00\x00\x00\x09\x00\x00\x00\x47\x00\x04\x00\x66\x01\x00\x00\x22\x00\x00\x00\x00\x00\x00\x00\x47\x00\x04\x00\x66\x01\x00\x00" +"\x21\x00\x00\x00\x04\x00\x00\x00\x47\x00\x04\x00\x9F\x01\x00\x00\x1E\x00\x00\x00\x04\x00\x00\x00\x47\x00\x04\x00\xBC\x01\x00\x00" +"\x22\x00\x00\x00\x00\x00\x00\x00\x47\x00\x04\x00\xBC\x01\x00\x00\x21\x00\x00\x00\x07\x00\x00\x00\x47\x00\x04\x00\xC4\x01\x00\x00" +"\x22\x00\x00\x00\x00\x00\x00\x00\x47\x00\x04\x00\xC4\x01\x00\x00\x21\x00\x00\x00\x06\x00\x00\x00\x47\x00\x04\x00\xD5\x01\x00\x00" +"\x01\x00\x00\x00\x11\x00\x00\x00\x47\x00\x04\x00\xD9\x01\x00\x00\x22\x00\x00\x00\x00\x00\x00\x00\x47\x00\x04\x00\xD9\x01\x00\x00" +"\x21\x00\x00\x00\x05\x00\x00\x00\x47\x00\x04\x00\xE8\x01\x00\x00\x01\x00\x00\x00\x05\x01\x00\x00\x47\x00\x04\x00\xEC\x01\x00\x00" +"\x01\x00\x00\x00\x06\x01\x00\x00\x48\x00\x04\x00\x02\x02\x00\x00\x00\x00\x00\x00\x05\x00\x00\x00\x48\x00\x05\x00\x02\x02\x00\x00" +"\x00\x00\x00\x00\x23\x00\x00\x00\x00\x00\x00\x00\x48\x00\x05\x00\x02\x02\x00\x00\x00\x00\x00\x00\x07\x00\x00\x00\x10\x00\x00\x00" +"\x48\x00\x05\x00\x02\x02\x00\x00\x01\x00\x00\x00\x23\x00\x00\x00\x40\x00\x00\x00\x48\x00\x05\x00\x02\x02\x00\x00\x02\x00\x00\x00" +"\x23\x00\x00\x00\x4C\x00\x00\x00\x48\x00\x05\x00\x02\x02\x00\x00\x03\x00\x00\x00\x23\x00\x00\x00\x50\x00\x00\x00\x48\x00\x05\x00" +"\x02\x02\x00\x00\x04\x00\x00\x00\x23\x00\x00\x00\x5C\x00\x00\x00\x48\x00\x05\x00\x02\x02\x00\x00\x05\x00\x00\x00\x23\x00\x00\x00" +"\x60\x00\x00\x00\x48\x00\x05\x00\x02\x02\x00\x00\x06\x00\x00\x00\x23\x00\x00\x00\x6C\x00\x00\x00\x48\x00\x05\x00\x02\x02\x00\x00" +"\x07\x00\x00\x00\x23\x00\x00\x00\x70\x00\x00\x00\x48\x00\x05\x00\x02\x02\x00\x00\x08\x00\x00\x00\x23\x00\x00\x00\x80\x00\x00\x00" +"\x48\x00\x05\x00\x02\x02\x00\x00\x09\x00\x00\x00\x23\x00\x00\x00\x88\x00\x00\x00\x47\x00\x03\x00\x02\x02\x00\x00\x02\x00\x00\x00" +"\x47\x00\x04\x00\x04\x02\x00\x00\x22\x00\x00\x00\x00\x00\x00\x00\x47\x00\x04\x00\x04\x02\x00\x00\x21\x00\x00\x00\x01\x00\x00\x00" +"\x13\x00\x02\x00\x02\x00\x00\x00\x21\x00\x03\x00\x03\x00\x00\x00\x02\x00\x00\x00\x16\x00\x03\x00\x06\x00\x00\x00\x20\x00\x00\x00" +"\x17\x00\x04\x00\x07\x00\x00\x00\x06\x00\x00\x00\x03\x00\x00\x00\x20\x00\x04\x00\x08\x00\x00\x00\x07\x00\x00\x00\x07\x00\x00\x00" +"\x21\x00\x04\x00\x09\x00\x00\x00\x07\x00\x00\x00\x08\x00\x00\x00\x17\x00\x04\x00\x0D\x00\x00\x00\x06\x00\x00\x00\x04\x00\x00\x00" +"\x20\x00\x04\x00\x0E\x00\x00\x00\x07\x00\x00\x00\x0D\x00\x00\x00\x21\x00\x04\x00\x0F\x00\x00\x00\x0D\x00\x00\x00\x0E\x00\x00\x00" +"\x19\x00\x09\x00\x13\x00\x00\x00\x06\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00" +"\x00\x00\x00\x00\x1B\x00\x03\x00\x14\x00\x00\x00\x13\x00\x00\x00\x20\x00\x04\x00\x15\x00\x00\x00\x00\x00\x00\x00\x14\x00\x00\x00" +"\x17\x00\x04\x00\x16\x00\x00\x00\x06\x00\x00\x00\x02\x00\x00\x00\x20\x00\x04\x00\x17\x00\x00\x00\x07\x00\x00\x00\x16\x00\x00\x00" +"\x21\x00\x06\x00\x18\x00\x00\x00\x16\x00\x00\x00\x15\x00\x00\x00\x17\x00\x00\x00\x08\x00\x00\x00\x15\x00\x04\x00\x1E\x00\x00\x00" +"\x20\x00\x00\x00\x01\x00\x00\x00\x32\x00\x04\x00\x1E\x00\x00\x00\x1F\x00\x00\x00\x15\x00\x00\x00\x2B\x00\x04\x00\x1E\x00\x00\x00" +"\x20\x00\x00\x00\x00\x00\x00\x00\x14\x00\x02\x00\x21\x00\x00\x00\x34\x00\x06\x00\x21\x00\x00\x00\x22\x00\x00\x00\xAB\x00\x00\x00" +"\x1F\x00\x00\x00\x20\x00\x00\x00\x34\x00\x05\x00\x21\x00\x00\x00\x23\x00\x00\x00\xA8\x00\x00\x00\x22\x00\x00\x00\x20\x00\x04\x00" +"\x28\x00\x00\x00\x07\x00\x00\x00\x06\x00\x00\x00\x18\x00\x04\x00\x2A\x00\x00\x00\x0D\x00\x00\x00\x04\x00\x00\x00\x15\x00\x04\x00" +"\x2B\x00\x00\x00\x20\x00\x00\x00\x00\x00\x00\x00\x2B\x00\x04\x00\x2B\x00\x00\x00\x2C\x00\x00\x00\x04\x00\x00\x00\x1C\x00\x04\x00" +"\x2D\x00\x00\x00\x0D\x00\x00\x00\x2C\x00\x00\x00\x1E\x00\x19\x00\x2E\x00\x00\x00\x2A\x00\x00\x00\x2A\x00\x00\x00\x2A\x00\x00\x00" +"\x07\x00\x00\x00\x06\x00\x00\x00\x07\x00\x00\x00\x06\x00\x00\x00\x07\x00\x00\x00\x06\x00\x00\x00\x07\x00\x00\x00\x06\x00\x00\x00" +"\x2D\x00\x00\x00\x07\x00\x00\x00\x06\x00\x00\x00\x07\x00\x00\x00\x06\x00\x00\x00\x07\x00\x00\x00\x06\x00\x00\x00\x0D\x00\x00\x00" +"\x0D\x00\x00\x00\x06\x00\x00\x00\x06\x00\x00\x00\x16\x00\x00\x00\x20\x00\x04\x00\x2F\x00\x00\x00\x02\x00\x00\x00\x2E\x00\x00\x00" +"\x3B\x00\x04\x00\x2F\x00\x00\x00\x30\x00\x00\x00\x02\x00\x00\x00\x2B\x00\x04\x00\x1E\x00\x00\x00\x31\x00\x00\x00\x14\x00\x00\x00" +"\x20\x00\x04\x00\x32\x00\x00\x00\x02\x00\x00\x00\x06\x00\x00\x00\x20\x00\x04\x00\x35\x00\x00\x00\x01\x00\x00\x00\x0D\x00\x00\x00" +"\x3B\x00\x04\x00\x35\x00\x00\x00\x36\x00\x00\x00\x01\x00\x00\x00\x2B\x00\x04\x00\x2B\x00\x00\x00\x37\x00\x00\x00\x02\x00\x00\x00" +"\x20\x00\x04\x00\x38\x00\x00\x00\x01\x00\x00\x00\x06\x00\x00\x00\x2B\x00\x04\x00\x2B\x00\x00\x00\x3C\x00\x00\x00\x03\x00\x00\x00" +"\x2B\x00\x04\x00\x06\x00\x00\x00\x40\x00\x00\x00\x00\x00\x00\x00\x2B\x00\x04\x00\x1E\x00\x00\x00\x42\x00\x00\x00\x15\x00\x00\x00" +"\x32\x00\x04\x00\x1E\x00\x00\x00\x47\x00\x00\x00\x03\x01\x00\x00\x34\x00\x06\x00\x21\x00\x00\x00\x48\x00\x00\x00\xAB\x00\x00\x00" +"\x47\x00\x00\x00\x20\x00\x00\x00\x2B\x00\x04\x00\x06\x00\x00\x00\x50\x00\x00\x00\x3B\xAA\xB8\x3F\x2B\x00\x04\x00\x06\x00\x00\x00" +"\x54\x00\x00\x00\x00\x00\x80\x3F\x2B\x00\x04\x00\x1E\x00\x00\x00\x55\x00\x00\x00\x13\x00\x00\x00\x20\x00\x04\x00\x5F\x00\x00\x00" +"\x02\x00\x00\x00\x0D\x00\x00\x00\x34\x00\x06\x00\x21\x00\x00\x00\x69\x00\x00\x00\xAB\x00\x00\x00\x1F\x00\x00\x00\x20\x00\x00\x00" +"\x34\x00\x05\x00\x21\x00\x00\x00\x6A\x00\x00\x00\xA8\x00\x00\x00\x69\x00\x00\x00\x2A\x00\x03\x00\x21\x00\x00\x00\x7C\x00\x00\x00" +"\x32\x00\x04\x00\x06\x00\x00\x00\x83\x00\x00\x00\x00\x80\x80\x43\x2B\x00\x04\x00\x06\x00\x00\x00\x86\x00\x00\x00\x00\x00\x80\xBF" +"\x2C\x00\x05\x00\x16\x00\x00\x00\x87\x00\x00\x00\x86\x00\x00\x00\x54\x00\x00\x00\x2B\x00\x04\x00\x06\x00\x00\x00\x94\x00\x00\x00" +"\x00\x00\x20\x41\x2B\x00\x04\x00\x06\x00\x00\x00\xB5\x00\x00\x00\x00\x00\xA0\x40\x2B\x00\x04\x00\x06\x00\x00\x00\xC2\x00\x00\x00" +"\x00\x00\x00\x3F\x32\x00\x04\x00\x06\x00\x00\x00\xD1\x00\x00\x00\x00\x00\x80\x43\x2B\x00\x04\x00\x06\x00\x00\x00\xE1\x00\x00\x00" +"\xFA\x7E\xAA\x3E\x20\x00\x04\x00\x02\x01\x00\x00\x01\x00\x00\x00\x16\x00\x00\x00\x3B\x00\x04\x00\x02\x01\x00\x00\x03\x01\x00\x00" +"\x01\x00\x00\x00\x3B\x00\x04\x00\x15\x00\x00\x00\x08\x01\x00\x00\x00\x00\x00\x00\x20\x00\x04\x00\x09\x01\x00\x00\x01\x00\x00\x00" +"\x07\x00\x00\x00\x3B\x00\x04\x00\x09\x01\x00\x00\x0A\x01\x00\x00\x01\x00\x00\x00\x20\x00\x04\x00\x10\x01\x00\x00\x03\x00\x00\x00" +"\x0D\x00\x00\x00\x3B\x00\x04\x00\x10\x01\x00\x00\x11\x01\x00\x00\x03\x00\x00\x00\x3B\x00\x04\x00\x15\x00\x00\x00\x12\x01\x00\x00" +"\x00\x00\x00\x00\x32\x00\x04\x00\x1E\x00\x00\x00\x16\x01\x00\x00\x10\x00\x00\x00\x34\x00\x06\x00\x21\x00\x00\x00\x17\x01\x00\x00" +"\xAB\x00\x00\x00\x16\x01\x00\x00\x20\x00\x00\x00\x32\x00\x04\x00\x06\x00\x00\x00\x1A\x01\x00\x00\x00\x00\x81\x43\x32\x00\x04\x00" +"\x1E\x00\x00\x00\x1D\x01\x00\x00\x13\x00\x00\x00\x34\x00\x06\x00\x21\x00\x00\x00\x1E\x01\x00\x00\xAB\x00\x00\x00\x1D\x01\x00\x00" +"\x20\x00\x00\x00\x34\x00\x06\x00\x21\x00\x00\x00\x2E\x01\x00\x00\xAB\x00\x00\x00\x1D\x01\x00\x00\x20\x00\x00\x00\x2C\x00\x06\x00" +"\x07\x00\x00\x00\x32\x01\x00\x00\x40\x00\x00\x00\x40\x00\x00\x00\x54\x00\x00\x00\x32\x00\x04\x00\x1E\x00\x00\x00\x33\x01\x00\x00" +"\x04\x01\x00\x00\x34\x00\x06\x00\x21\x00\x00\x00\x34\x01\x00\x00\xAB\x00\x00\x00\x33\x01\x00\x00\x20\x00\x00\x00\x3B\x00\x04\x00" +"\x35\x00\x00\x00\x38\x01\x00\x00\x01\x00\x00\x00\x2B\x00\x04\x00\x1E\x00\x00\x00\x3B\x01\x00\x00\x0B\x00\x00\x00\x3B\x00\x04\x00" +"\x15\x00\x00\x00\x41\x01\x00\x00\x00\x00\x00\x00\x3B\x00\x04\x00\x02\x01\x00\x00\x43\x01\x00\x00\x01\x00\x00\x00\x2B\x00\x04\x00" +"\x06\x00\x00\x00\x4D\x01\x00\x00\x00\x00\x00\x40\x3B\x00\x04\x00\x15\x00\x00\x00\x4E\x01\x00\x00\x00\x00\x00\x00\x2B\x00\x04\x00" +"\x06\x00\x00\x00\x56\x01\x00\x00\x00\x00\x80\x3E\x3B\x00\x04\x00\x15\x00\x00\x00\x66\x01\x00\x00\x00\x00\x00\x00\x2B\x00\x04\x00" +"\x06\x00\x00\x00\x82\x01\x00\x00\x00\x00\x00\x42\x34\x00\x06\x00\x21\x00\x00\x00\x92\x01\x00\x00\xAB\x00\x00\x00\x1D\x01\x00\x00" +"\x20\x00\x00\x00\x2B\x00\x04\x00\x2B\x00\x00\x00\x9A\x01\x00\x00\x00\x00\x00\x00\x18\x00\x04\x00\x9D\x01\x00\x00\x07\x00\x00\x00" +"\x03\x00\x00\x00\x20\x00\x04\x00\x9E\x01\x00\x00\x01\x00\x00\x00\x9D\x01\x00\x00\x3B\x00\x04\x00\x9E\x01\x00\x00\x9F\x01\x00\x00" +"\x01\x00\x00\x00\x2B\x00\x04\x00\x2B\x00\x00\x00\xA3\x01\x00\x00\x01\x00\x00\x00\x2B\x00\x04\x00\x1E\x00\x00\x00\xA6\x01\x00\x00" +"\x01\x00\x00\x00\x2B\x00\x04\x00\x1E\x00\x00\x00\xAD\x01\x00\x00\x02\x00\x00\x00\x20\x00\x04\x00\xB2\x01\x00\x00\x02\x00\x00\x00" +"\x2A\x00\x00\x00\x3B\x00\x04\x00\x15\x00\x00\x00\xBC\x01\x00\x00\x00\x00\x00\x00\x19\x00\x09\x00\xC1\x01\x00\x00\x06\x00\x00\x00" +"\x03\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x1B\x00\x03\x00\xC2\x01\x00\x00" +"\xC1\x01\x00\x00\x20\x00\x04\x00\xC3\x01\x00\x00\x00\x00\x00\x00\xC2\x01\x00\x00\x3B\x00\x04\x00\xC3\x01\x00\x00\xC4\x01\x00\x00" +"\x00\x00\x00\x00\x32\x00\x04\x00\x1E\x00\x00\x00\xD5\x01\x00\x00\x11\x00\x00\x00\x34\x00\x06\x00\x21\x00\x00\x00\xD6\x01\x00\x00" +"\xAB\x00\x00\x00\xD5\x01\x00\x00\x20\x00\x00\x00\x3B\x00\x04\x00\x15\x00\x00\x00\xD9\x01\x00\x00\x00\x00\x00\x00\x2B\x00\x04\x00" +"\x1E\x00\x00\x00\xE4\x01\x00\x00\x12\x00\x00\x00\x32\x00\x04\x00\x06\x00\x00\x00\xE8\x01\x00\x00\x00\x80\x82\x43\x32\x00\x04\x00" +"\x1E\x00\x00\x00\xEC\x01\x00\x00\x06\x01\x00\x00\x34\x00\x06\x00\x21\x00\x00\x00\xED\x01\x00\x00\xAB\x00\x00\x00\xEC\x01\x00\x00" +"\x20\x00\x00\x00\x20\x00\x04\x00\xF0\x01\x00\x00\x03\x00\x00\x00\x06\x00\x00\x00\x1E\x00\x0C\x00\x02\x02\x00\x00\x2A\x00\x00\x00" +"\x07\x00\x00\x00\x06\x00\x00\x00\x07\x00\x00\x00\x06\x00\x00\x00\x07\x00\x00\x00\x06\x00\x00\x00\x0D\x00\x00\x00\x16\x00\x00\x00" +"\x16\x00\x00\x00\x20\x00\x04\x00\x03\x02\x00\x00\x02\x00\x00\x00\x02\x02\x00\x00\x3B\x00\x04\x00\x03\x02\x00\x00\x04\x02\x00\x00" +"\x02\x00\x00\x00\x36\x00\x05\x00\x02\x00\x00\x00\x04\x00\x00\x00\x00\x00\x00\x00\x03\x00\x00\x00\xF8\x00\x02\x00\x05\x00\x00\x00" +"\x3B\x00\x04\x00\x17\x00\x00\x00\x01\x01\x00\x00\x07\x00\x00\x00\x3B\x00\x04\x00\x17\x00\x00\x00\x0B\x01\x00\x00\x07\x00\x00\x00" +"\x3B\x00\x04\x00\x08\x00\x00\x00\x0D\x01\x00\x00\x07\x00\x00\x00\x3B\x00\x04\x00\x08\x00\x00\x00\x23\x01\x00\x00\x07\x00\x00\x00" +"\x3B\x00\x04\x00\x08\x00\x00\x00\x37\x01\x00\x00\x07\x00\x00\x00\x3B\x00\x04\x00\x08\x00\x00\x00\x4C\x01\x00\x00\x07\x00\x00\x00" +"\x3B\x00\x04\x00\x0E\x00\x00\x00\x65\x01\x00\x00\x07\x00\x00\x00\x3B\x00\x04\x00\x08\x00\x00\x00\x6C\x01\x00\x00\x07\x00\x00\x00" +"\x3B\x00\x04\x00\x28\x00\x00\x00\x7D\x01\x00\x00\x07\x00\x00\x00\x3B\x00\x04\x00\x08\x00\x00\x00\x95\x01\x00\x00\x07\x00\x00\x00" +"\x3B\x00\x04\x00\x0E\x00\x00\x00\xFF\x01\x00\x00\x07\x00\x00\x00\x3D\x00\x04\x00\x16\x00\x00\x00\x04\x01\x00\x00\x03\x01\x00\x00" +"\x3E\x00\x03\x00\x01\x01\x00\x00\x04\x01\x00\x00\xBA\x00\x05\x00\x21\x00\x00\x00\x05\x01\x00\x00\xD1\x00\x00\x00\x40\x00\x00\x00" +"\xF7\x00\x03\x00\x07\x01\x00\x00\x00\x00\x00\x00\xFA\x00\x04\x00\x05\x01\x00\x00\x06\x01\x00\x00\x07\x01\x00\x00\xF8\x00\x02\x00" +"\x06\x01\x00\x00\x3D\x00\x04\x00\x16\x00\x00\x00\x0C\x01\x00\x00\x01\x01\x00\x00\x3E\x00\x03\x00\x0B\x01\x00\x00\x0C\x01\x00\x00" +"\x3D\x00\x04\x00\x07\x00\x00\x00\x0E\x01\x00\x00\x0A\x01\x00\x00\x3E\x00\x03\x00\x0D\x01\x00\x00\x0E\x01\x00\x00\x39\x00\x07\x00" +"\x16\x00\x00\x00\x0F\x01\x00\x00\x1C\x00\x00\x00\x08\x01\x00\x00\x0B\x01\x00\x00\x0D\x01\x00\x00\x3E\x00\x03\x00\x01\x01\x00\x00" +"\x0F\x01\x00\x00\xF9\x00\x02\x00\x07\x01\x00\x00\xF8\x00\x02\x00\x07\x01\x00\x00\x3D\x00\x04\x00\x14\x00\x00\x00\x13\x01\x00\x00" +"\x12\x01\x00\x00\x3D\x00\x04\x00\x16\x00\x00\x00\x14\x01\x00\x00\x01\x01\x00\x00\x57\x00\x05\x00\x0D\x00\x00\x00\x15\x01\x00\x00" +"\x13\x01\x00\x00\x14\x01\x00\x00\x3E\x00\x03\x00\x11\x01\x00\x00\x15\x01\x00\x00\xF7\x00\x03\x00\x19\x01\x00\x00\x00\x00\x00\x00" +"\xFA\x00\x04\x00\x17\x01\x00\x00\x18\x01\x00\x00\x19\x01\x00\x00\xF8\x00\x02\x00\x18\x01\x00\x00\xBA\x00\x05\x00\x21\x00\x00\x00" +"\x1B\x01\x00\x00\x1A\x01\x00\x00\x40\x00\x00\x00\xA6\x00\x05\x00\x21\x00\x00\x00\x1C\x01\x00\x00\x7C\x00\x00\x00\x1B\x01\x00\x00" +"\xA6\x00\x05\x00\x21\x00\x00\x00\x1F\x01\x00\x00\x1C\x01\x00\x00\x1E\x01\x00\x00\xF9\x00\x02\x00\x19\x01\x00\x00\xF8\x00\x02\x00" +"\x19\x01\x00\x00\xF5\x00\x07\x00\x21\x00\x00\x00\x20\x01\x00\x00\x17\x01\x00\x00\x07\x01\x00\x00\x1F\x01\x00\x00\x18\x01\x00\x00" +"\xF7\x00\x03\x00\x22\x01\x00\x00\x00\x00\x00\x00\xFA\x00\x04\x00\x20\x01\x00\x00\x21\x01\x00\x00\x2B\x01\x00\x00\xF8\x00\x02\x00" +"\x21\x01\x00\x00\x3D\x00\x04\x00\x14\x00\x00\x00\x24\x01\x00\x00\x08\x01\x00\x00\x3D\x00\x04\x00\x16\x00\x00\x00\x25\x01\x00\x00" +"\x01\x01\x00\x00\x57\x00\x05\x00\x0D\x00\x00\x00\x26\x01\x00\x00\x24\x01\x00\x00\x25\x01\x00\x00\x4F\x00\x08\x00\x07\x00\x00\x00" +"\x27\x01\x00\x00\x26\x01\x00\x00\x26\x01\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x02\x00\x00\x00\x50\x00\x06\x00\x07\x00\x00\x00" +"\x28\x01\x00\x00\xC2\x00\x00\x00\xC2\x00\x00\x00\xC2\x00\x00\x00\x83\x00\x05\x00\x07\x00\x00\x00\x29\x01\x00\x00\x27\x01\x00\x00" +"\x28\x01\x00\x00\x0C\x00\x06\x00\x07\x00\x00\x00\x2A\x01\x00\x00\x01\x00\x00\x00\x45\x00\x00\x00\x29\x01\x00\x00\x3E\x00\x03\x00" +"\x23\x01\x00\x00\x2A\x01\x00\x00\xF9\x00\x02\x00\x22\x01\x00\x00\xF8\x00\x02\x00\x2B\x01\x00\x00\xBA\x00\x05\x00\x21\x00\x00\x00" +"\x2C\x01\x00\x00\x1A\x01\x00\x00\x40\x00\x00\x00\xA6\x00\x05\x00\x21\x00\x00\x00\x2D\x01\x00\x00\x2C\x01\x00\x00\x7C\x00\x00\x00" +"\xA6\x00\x05\x00\x21\x00\x00\x00\x2F\x01\x00\x00\x2D\x01\x00\x00\x2E\x01\x00\x00\xF7\x00\x03\x00\x31\x01\x00\x00\x00\x00\x00\x00" +"\xFA\x00\x04\x00\x2F\x01\x00\x00\x30\x01\x00\x00\x31\x01\x00\x00\xF8\x00\x02\x00\x30\x01\x00\x00\x3E\x00\x03\x00\x23\x01\x00\x00" +"\x32\x01\x00\x00\xF9\x00\x02\x00\x31\x01\x00\x00\xF8\x00\x02\x00\x31\x01\x00\x00\xF9\x00\x02\x00\x22\x01\x00\x00\xF8\x00\x02\x00" +"\x22\x01\x00\x00\xF7\x00\x03\x00\x36\x01\x00\x00\x00\x00\x00\x00\xFA\x00\x04\x00\x34\x01\x00\x00\x35\x01\x00\x00\x40\x01\x00\x00" +"\xF8\x00\x02\x00\x35\x01\x00\x00\x3D\x00\x04\x00\x0D\x00\x00\x00\x39\x01\x00\x00\x38\x01\x00\x00\x4F\x00\x08\x00\x07\x00\x00\x00" +"\x3A\x01\x00\x00\x39\x01\x00\x00\x39\x01\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x02\x00\x00\x00\x41\x00\x06\x00\x5F\x00\x00\x00" +"\x3C\x01\x00\x00\x30\x00\x00\x00\x3B\x01\x00\x00\x20\x00\x00\x00\x3D\x00\x04\x00\x0D\x00\x00\x00\x3D\x01\x00\x00\x3C\x01\x00\x00" +"\x4F\x00\x08\x00\x07\x00\x00\x00\x3E\x01\x00\x00\x3D\x01\x00\x00\x3D\x01\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x02\x00\x00\x00" +"\x85\x00\x05\x00\x07\x00\x00\x00\x3F\x01\x00\x00\x3A\x01\x00\x00\x3E\x01\x00\x00\x3E\x00\x03\x00\x37\x01\x00\x00\x3F\x01\x00\x00" +"\xF9\x00\x02\x00\x36\x01\x00\x00\xF8\x00\x02\x00\x40\x01\x00\x00\x3D\x00\x04\x00\x14\x00\x00\x00\x42\x01\x00\x00\x41\x01\x00\x00" +"\x3D\x00\x04\x00\x16\x00\x00\x00\x44\x01\x00\x00\x43\x01\x00\x00\x57\x00\x05\x00\x0D\x00\x00\x00\x45\x01\x00\x00\x42\x01\x00\x00" +"\x44\x01\x00\x00\x41\x00\x06\x00\x5F\x00\x00\x00\x46\x01\x00\x00\x30\x00\x00\x00\x3B\x01\x00\x00\x20\x00\x00\x00\x3D\x00\x04\x00" +"\x0D\x00\x00\x00\x47\x01\x00\x00\x46\x01\x00\x00\x85\x00\x05\x00\x0D\x00\x00\x00\x48\x01\x00\x00\x45\x01\x00\x00\x47\x01\x00\x00" +"\x4F\x00\x08\x00\x07\x00\x00\x00\x49\x01\x00\x00\x48\x01\x00\x00\x48\x01\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x02\x00\x00\x00" +"\x3E\x00\x03\x00\x37\x01\x00\x00\x49\x01\x00\x00\xF7\x00\x03\x00\x4B\x01\x00\x00\x00\x00\x00\x00\xFA\x00\x04\x00\x7C\x00\x00\x00" +"\x4A\x01\x00\x00\x4B\x01\x00\x00\xF8\x00\x02\x00\x4A\x01\x00\x00\x3D\x00\x04\x00\x14\x00\x00\x00\x4F\x01\x00\x00\x4E\x01\x00\x00" +"\x3D\x00\x04\x00\x16\x00\x00\x00\x50\x01\x00\x00\x43\x01\x00\x00\x57\x00\x05\x00\x0D\x00\x00\x00\x51\x01\x00\x00\x4F\x01\x00\x00" +"\x50\x01\x00\x00\x4F\x00\x08\x00\x07\x00\x00\x00\x52\x01\x00\x00\x51\x01\x00\x00\x51\x01\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00" +"\x02\x00\x00\x00\x50\x00\x06\x00\x07\x00\x00\x00\x53\x01\x00\x00\xC2\x00\x00\x00\xC2\x00\x00\x00\xC2\x00\x00\x00\x83\x00\x05\x00" +"\x07\x00\x00\x00\x54\x01\x00\x00\x52\x01\x00\x00\x53\x01\x00\x00\x8E\x00\x05\x00\x07\x00\x00\x00\x55\x01\x00\x00\x54\x01\x00\x00" +"\x4D\x01\x00\x00\x3E\x00\x03\x00\x4C\x01\x00\x00\x55\x01\x00\x00\x41\x00\x05\x00\x28\x00\x00\x00\x57\x01\x00\x00\x4C\x01\x00\x00" +"\x37\x00\x00\x00\x3D\x00\x04\x00\x06\x00\x00\x00\x58\x01\x00\x00\x57\x01\x00\x00\x0C\x00\x07\x00\x06\x00\x00\x00\x59\x01\x00\x00" +"\x01\x00\x00\x00\x28\x00\x00\x00\x56\x01\x00\x00\x58\x01\x00\x00\x88\x00\x05\x00\x06\x00\x00\x00\x5A\x01\x00\x00\x54\x00\x00\x00" +"\x59\x01\x00\x00\x3D\x00\x04\x00\x07\x00\x00\x00\x5B\x01\x00\x00\x37\x01\x00\x00\x8E\x00\x05\x00\x07\x00\x00\x00\x5C\x01\x00\x00" +"\x5B\x01\x00\x00\x5A\x01\x00\x00\x3E\x00\x03\x00\x37\x01\x00\x00\x5C\x01\x00\x00\x3D\x00\x04\x00\x07\x00\x00\x00\x5D\x01\x00\x00" +"\x23\x01\x00\x00\x3D\x00\x04\x00\x07\x00\x00\x00\x5E\x01\x00\x00\x4C\x01\x00\x00\x94\x00\x05\x00\x06\x00\x00\x00\x5F\x01\x00\x00" +"\x5D\x01\x00\x00\x5E\x01\x00\x00\x3D\x00\x04\x00\x07\x00\x00\x00\x60\x01\x00\x00\x37\x01\x00\x00\x8E\x00\x05\x00\x07\x00\x00\x00" +"\x61\x01\x00\x00\x60\x01\x00\x00\x5F\x01\x00\x00\x3E\x00\x03\x00\x37\x01\x00\x00\x61\x01\x00\x00\xF9\x00\x02\x00\x4B\x01\x00\x00" +"\xF8\x00\x02\x00\x4B\x01\x00\x00\xF9\x00\x02\x00\x36\x01\x00\x00\xF8\x00\x02\x00\x36\x01\x00\x00\xBA\x00\x05\x00\x21\x00\x00\x00" +"\x62\x01\x00\x00\x1A\x01\x00\x00\x40\x00\x00\x00\xF7\x00\x03\x00\x64\x01\x00\x00\x00\x00\x00\x00\xFA\x00\x04\x00\x62\x01\x00\x00" +"\x63\x01\x00\x00\x64\x01\x00\x00\xF8\x00\x02\x00\x63\x01\x00\x00\x3D\x00\x04\x00\x14\x00\x00\x00\x67\x01\x00\x00\x66\x01\x00\x00" +"\x3D\x00\x04\x00\x16\x00\x00\x00\x68\x01\x00\x00\x01\x01\x00\x00\x57\x00\x05\x00\x0D\x00\x00\x00\x69\x01\x00\x00\x67\x01\x00\x00" +"\x68\x01\x00\x00\x3E\x00\x03\x00\x65\x01\x00\x00\x69\x01\x00\x00\xF7\x00\x03\x00\x6B\x01\x00\x00\x00\x00\x00\x00\xFA\x00\x04\x00" +"\x7C\x00\x00\x00\x6A\x01\x00\x00\x78\x01\x00\x00\xF8\x00\x02\x00\x6A\x01\x00\x00\x3D\x00\x04\x00\x07\x00\x00\x00\x6D\x01\x00\x00" +"\x0A\x01\x00\x00\x0C\x00\x06\x00\x07\x00\x00\x00\x6E\x01\x00\x00\x01\x00\x00\x00\x45\x00\x00\x00\x6D\x01\x00\x00\x3D\x00\x04\x00" +"\x14\x00\x00\x00\x6F\x01\x00\x00\x4E\x01\x00\x00\x3D\x00\x04\x00\x16\x00\x00\x00\x70\x01\x00\x00\x43\x01\x00\x00\x57\x00\x05\x00" +"\x0D\x00\x00\x00\x71\x01\x00\x00\x6F\x01\x00\x00\x70\x01\x00\x00\x4F\x00\x08\x00\x07\x00\x00\x00\x72\x01\x00\x00\x71\x01\x00\x00" +"\x71\x01\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x02\x00\x00\x00\x50\x00\x06\x00\x07\x00\x00\x00\x73\x01\x00\x00\xC2\x00\x00\x00" +"\xC2\x00\x00\x00\xC2\x00\x00\x00\x83\x00\x05\x00\x07\x00\x00\x00\x74\x01\x00\x00\x72\x01\x00\x00\x73\x01\x00\x00\x8E\x00\x05\x00" +"\x07\x00\x00\x00\x75\x01\x00\x00\x74\x01\x00\x00\x4D\x01\x00\x00\x81\x00\x05\x00\x07\x00\x00\x00\x76\x01\x00\x00\x6E\x01\x00\x00" +"\x75\x01\x00\x00\x0C\x00\x06\x00\x07\x00\x00\x00\x77\x01\x00\x00\x01\x00\x00\x00\x45\x00\x00\x00\x76\x01\x00\x00\x3E\x00\x03\x00" +"\x6C\x01\x00\x00\x77\x01\x00\x00\xF9\x00\x02\x00\x6B\x01\x00\x00\xF8\x00\x02\x00\x78\x01\x00\x00\x3D\x00\x04\x00\x07\x00\x00\x00" +"\x79\x01\x00\x00\x0A\x01\x00\x00\x0C\x00\x06\x00\x07\x00\x00\x00\x7A\x01\x00\x00\x01\x00\x00\x00\x45\x00\x00\x00\x79\x01\x00\x00" +"\x81\x00\x05\x00\x07\x00\x00\x00\x7B\x01\x00\x00\x7A\x01\x00\x00\x32\x01\x00\x00\x0C\x00\x06\x00\x07\x00\x00\x00\x7C\x01\x00\x00" +"\x01\x00\x00\x00\x45\x00\x00\x00\x7B\x01\x00\x00\x3E\x00\x03\x00\x6C\x01\x00\x00\x7C\x01\x00\x00\xF9\x00\x02\x00\x6B\x01\x00\x00" +"\xF8\x00\x02\x00\x6B\x01\x00\x00\x3D\x00\x04\x00\x07\x00\x00\x00\x7E\x01\x00\x00\x6C\x01\x00\x00\x3D\x00\x04\x00\x07\x00\x00\x00" +"\x7F\x01\x00\x00\x23\x01\x00\x00\x94\x00\x05\x00\x06\x00\x00\x00\x80\x01\x00\x00\x7E\x01\x00\x00\x7F\x01\x00\x00\x0C\x00\x07\x00" +"\x06\x00\x00\x00\x81\x01\x00\x00\x01\x00\x00\x00\x28\x00\x00\x00\x80\x01\x00\x00\x40\x00\x00\x00\x41\x00\x05\x00\x28\x00\x00\x00" +"\x83\x01\x00\x00\x65\x01\x00\x00\x3C\x00\x00\x00\x3D\x00\x04\x00\x06\x00\x00\x00\x84\x01\x00\x00\x83\x01\x00\x00\x85\x00\x05\x00" +"\x06\x00\x00\x00\x85\x01\x00\x00\x82\x01\x00\x00\x84\x01\x00\x00\x0C\x00\x07\x00\x06\x00\x00\x00\x86\x01\x00\x00\x01\x00\x00\x00" +"\x1A\x00\x00\x00\x81\x01\x00\x00\x85\x01\x00\x00\x3E\x00\x03\x00\x7D\x01\x00\x00\x86\x01\x00\x00\x3D\x00\x04\x00\x06\x00\x00\x00" +"\x87\x01\x00\x00\x7D\x01\x00\x00\x85\x00\x05\x00\x06\x00\x00\x00\x88\x01\x00\x00\x87\x01\x00\x00\x1A\x01\x00\x00\x3E\x00\x03\x00" +"\x7D\x01\x00\x00\x88\x01\x00\x00\x3D\x00\x04\x00\x06\x00\x00\x00\x89\x01\x00\x00\x7D\x01\x00\x00\x3D\x00\x04\x00\x0D\x00\x00\x00" +"\x8A\x01\x00\x00\x65\x01\x00\x00\x4F\x00\x08\x00\x07\x00\x00\x00\x8B\x01\x00\x00\x8A\x01\x00\x00\x8A\x01\x00\x00\x00\x00\x00\x00" +"\x01\x00\x00\x00\x02\x00\x00\x00\x8E\x00\x05\x00\x07\x00\x00\x00\x8C\x01\x00\x00\x8B\x01\x00\x00\x89\x01\x00\x00\x3D\x00\x04\x00" +"\x0D\x00\x00\x00\x8D\x01\x00\x00\x11\x01\x00\x00\x4F\x00\x08\x00\x07\x00\x00\x00\x8E\x01\x00\x00\x8D\x01\x00\x00\x8D\x01\x00\x00" +"\x00\x00\x00\x00\x01\x00\x00\x00\x02\x00\x00\x00\x81\x00\x05\x00\x07\x00\x00\x00\x8F\x01\x00\x00\x8E\x01\x00\x00\x8C\x01\x00\x00" +"\x3D\x00\x04\x00\x0D\x00\x00\x00\x90\x01\x00\x00\x11\x01\x00\x00\x4F\x00\x09\x00\x0D\x00\x00\x00\x91\x01\x00\x00\x90\x01\x00\x00" +"\x8F\x01\x00\x00\x04\x00\x00\x00\x05\x00\x00\x00\x06\x00\x00\x00\x03\x00\x00\x00\x3E\x00\x03\x00\x11\x01\x00\x00\x91\x01\x00\x00" +"\xF9\x00\x02\x00\x64\x01\x00\x00\xF8\x00\x02\x00\x64\x01\x00\x00\xF7\x00\x03\x00\x94\x01\x00\x00\x00\x00\x00\x00\xFA\x00\x04\x00" +"\x92\x01\x00\x00\x93\x01\x00\x00\x94\x01\x00\x00\xF8\x00\x02\x00\x93\x01\x00\x00\x3D\x00\x04\x00\x07\x00\x00\x00\x96\x01\x00\x00" +"\x0A\x01\x00\x00\x7F\x00\x04\x00\x07\x00\x00\x00\x97\x01\x00\x00\x96\x01\x00\x00\x3D\x00\x04\x00\x07\x00\x00\x00\x98\x01\x00\x00" +"\x23\x01\x00\x00\x0C\x00\x07\x00\x07\x00\x00\x00\x99\x01\x00\x00\x01\x00\x00\x00\x47\x00\x00\x00\x97\x01\x00\x00\x98\x01\x00\x00" +"\x3E\x00\x03\x00\x95\x01\x00\x00\x99\x01\x00\x00\x41\x00\x05\x00\x28\x00\x00\x00\x9B\x01\x00\x00\x95\x01\x00\x00\x9A\x01\x00\x00" +"\x3D\x00\x04\x00\x06\x00\x00\x00\x9C\x01\x00\x00\x9B\x01\x00\x00\x41\x00\x05\x00\x09\x01\x00\x00\xA0\x01\x00\x00\x9F\x01\x00\x00" +"\x20\x00\x00\x00\x3D\x00\x04\x00\x07\x00\x00\x00\xA1\x01\x00\x00\xA0\x01\x00\x00\x8E\x00\x05\x00\x07\x00\x00\x00\xA2\x01\x00\x00" +"\xA1\x01\x00\x00\x9C\x01\x00\x00\x41\x00\x05\x00\x28\x00\x00\x00\xA4\x01\x00\x00\x95\x01\x00\x00\xA3\x01\x00\x00\x3D\x00\x04\x00" +"\x06\x00\x00\x00\xA5\x01\x00\x00\xA4\x01\x00\x00\x41\x00\x05\x00\x09\x01\x00\x00\xA7\x01\x00\x00\x9F\x01\x00\x00\xA6\x01\x00\x00" +"\x3D\x00\x04\x00\x07\x00\x00\x00\xA8\x01\x00\x00\xA7\x01\x00\x00\x8E\x00\x05\x00\x07\x00\x00\x00\xA9\x01\x00\x00\xA8\x01\x00\x00" +"\xA5\x01\x00\x00\x81\x00\x05\x00\x07\x00\x00\x00\xAA\x01\x00\x00\xA2\x01\x00\x00\xA9\x01\x00\x00\x41\x00\x05\x00\x28\x00\x00\x00" +"\xAB\x01\x00\x00\x95\x01\x00\x00\x37\x00\x00\x00\x3D\x00\x04\x00\x06\x00\x00\x00\xAC\x01\x00\x00\xAB\x01\x00\x00\x41\x00\x05\x00" +"\x09\x01\x00\x00\xAE\x01\x00\x00\x9F\x01\x00\x00\xAD\x01\x00\x00\x3D\x00\x04\x00\x07\x00\x00\x00\xAF\x01\x00\x00\xAE\x01\x00\x00" +"\x8E\x00\x05\x00\x07\x00\x00\x00\xB0\x01\x00\x00\xAF\x01\x00\x00\xAC\x01\x00\x00\x81\x00\x05\x00\x07\x00\x00\x00\xB1\x01\x00\x00" +"\xAA\x01\x00\x00\xB0\x01\x00\x00\x3E\x00\x03\x00\x95\x01\x00\x00\xB1\x01\x00\x00\x41\x00\x05\x00\xB2\x01\x00\x00\xB3\x01\x00\x00" +"\x30\x00\x00\x00\xA6\x01\x00\x00\x3D\x00\x04\x00\x2A\x00\x00\x00\xB4\x01\x00\x00\xB3\x01\x00\x00\x3D\x00\x04\x00\x07\x00\x00\x00" +"\xB5\x01\x00\x00\x95\x01\x00\x00\x51\x00\x05\x00\x06\x00\x00\x00\xB6\x01\x00\x00\xB5\x01\x00\x00\x00\x00\x00\x00\x51\x00\x05\x00" +"\x06\x00\x00\x00\xB7\x01\x00\x00\xB5\x01\x00\x00\x01\x00\x00\x00\x51\x00\x05\x00\x06\x00\x00\x00\xB8\x01\x00\x00\xB5\x01\x00\x00" +"\x02\x00\x00\x00\x50\x00\x07\x00\x0D\x00\x00\x00\xB9\x01\x00\x00\xB6\x01\x00\x00\xB7\x01\x00\x00\xB8\x01\x00\x00\x40\x00\x00\x00" +"\x91\x00\x05\x00\x0D\x00\x00\x00\xBA\x01\x00\x00\xB4\x01\x00\x00\xB9\x01\x00\x00\x4F\x00\x08\x00\x07\x00\x00\x00\xBB\x01\x00\x00" +"\xBA\x01\x00\x00\xBA\x01\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x02\x00\x00\x00\x3E\x00\x03\x00\x95\x01\x00\x00\xBB\x01\x00\x00" +"\x3D\x00\x04\x00\x14\x00\x00\x00\xBD\x01\x00\x00\xBC\x01\x00\x00\x3D\x00\x04\x00\x16\x00\x00\x00\xBE\x01\x00\x00\x01\x01\x00\x00" +"\x57\x00\x05\x00\x0D\x00\x00\x00\xBF\x01\x00\x00\xBD\x01\x00\x00\xBE\x01\x00\x00\x4F\x00\x08\x00\x07\x00\x00\x00\xC0\x01\x00\x00" +"\xBF\x01\x00\x00\xBF\x01\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x02\x00\x00\x00\x3D\x00\x04\x00\xC2\x01\x00\x00\xC5\x01\x00\x00" +"\xC4\x01\x00\x00\x3D\x00\x04\x00\x07\x00\x00\x00\xC6\x01\x00\x00\x95\x01\x00\x00\x57\x00\x05\x00\x0D\x00\x00\x00\xC7\x01\x00\x00" +"\xC5\x01\x00\x00\xC6\x01\x00\x00\x4F\x00\x08\x00\x07\x00\x00\x00\xC8\x01\x00\x00\xC7\x01\x00\x00\xC7\x01\x00\x00\x00\x00\x00\x00" +"\x01\x00\x00\x00\x02\x00\x00\x00\x85\x00\x05\x00\x07\x00\x00\x00\xC9\x01\x00\x00\xC0\x01\x00\x00\xC8\x01\x00\x00\x3D\x00\x04\x00" +"\x0D\x00\x00\x00\xCA\x01\x00\x00\x11\x01\x00\x00\x4F\x00\x08\x00\x07\x00\x00\x00\xCB\x01\x00\x00\xCA\x01\x00\x00\xCA\x01\x00\x00" +"\x00\x00\x00\x00\x01\x00\x00\x00\x02\x00\x00\x00\x81\x00\x05\x00\x07\x00\x00\x00\xCC\x01\x00\x00\xCB\x01\x00\x00\xC9\x01\x00\x00" +"\x3D\x00\x04\x00\x0D\x00\x00\x00\xCD\x01\x00\x00\x11\x01\x00\x00\x4F\x00\x09\x00\x0D\x00\x00\x00\xCE\x01\x00\x00\xCD\x01\x00\x00" +"\xCC\x01\x00\x00\x04\x00\x00\x00\x05\x00\x00\x00\x06\x00\x00\x00\x03\x00\x00\x00\x3E\x00\x03\x00\x11\x01\x00\x00\xCE\x01\x00\x00" +"\xF9\x00\x02\x00\x94\x01\x00\x00\xF8\x00\x02\x00\x94\x01\x00\x00\x3D\x00\x04\x00\x07\x00\x00\x00\xCF\x01\x00\x00\x37\x01\x00\x00" +"\x3D\x00\x04\x00\x0D\x00\x00\x00\xD0\x01\x00\x00\x11\x01\x00\x00\x4F\x00\x08\x00\x07\x00\x00\x00\xD1\x01\x00\x00\xD0\x01\x00\x00" +"\xD0\x01\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x02\x00\x00\x00\x85\x00\x05\x00\x07\x00\x00\x00\xD2\x01\x00\x00\xD1\x01\x00\x00" +"\xCF\x01\x00\x00\x3D\x00\x04\x00\x0D\x00\x00\x00\xD3\x01\x00\x00\x11\x01\x00\x00\x4F\x00\x09\x00\x0D\x00\x00\x00\xD4\x01\x00\x00" +"\xD3\x01\x00\x00\xD2\x01\x00\x00\x04\x00\x00\x00\x05\x00\x00\x00\x06\x00\x00\x00\x03\x00\x00\x00\x3E\x00\x03\x00\x11\x01\x00\x00" +"\xD4\x01\x00\x00\xF7\x00\x03\x00\xD8\x01\x00\x00\x00\x00\x00\x00\xFA\x00\x04\x00\xD6\x01\x00\x00\xD7\x01\x00\x00\xD8\x01\x00\x00" +"\xF8\x00\x02\x00\xD7\x01\x00\x00\x3D\x00\x04\x00\x14\x00\x00\x00\xDA\x01\x00\x00\xD9\x01\x00\x00\x3D\x00\x04\x00\x16\x00\x00\x00" +"\xDB\x01\x00\x00\x01\x01\x00\x00\x57\x00\x05\x00\x0D\x00\x00\x00\xDC\x01\x00\x00\xDA\x01\x00\x00\xDB\x01\x00\x00\x4F\x00\x08\x00" +"\x07\x00\x00\x00\xDD\x01\x00\x00\xDC\x01\x00\x00\xDC\x01\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x02\x00\x00\x00\x3D\x00\x04\x00" +"\x0D\x00\x00\x00\xDE\x01\x00\x00\x11\x01\x00\x00\x4F\x00\x08\x00\x07\x00\x00\x00\xDF\x01\x00\x00\xDE\x01\x00\x00\xDE\x01\x00\x00" +"\x00\x00\x00\x00\x01\x00\x00\x00\x02\x00\x00\x00\x81\x00\x05\x00\x07\x00\x00\x00\xE0\x01\x00\x00\xDF\x01\x00\x00\xDD\x01\x00\x00" +"\x3D\x00\x04\x00\x0D\x00\x00\x00\xE1\x01\x00\x00\x11\x01\x00\x00\x4F\x00\x09\x00\x0D\x00\x00\x00\xE2\x01\x00\x00\xE1\x01\x00\x00" +"\xE0\x01\x00\x00\x04\x00\x00\x00\x05\x00\x00\x00\x06\x00\x00\x00\x03\x00\x00\x00\x3E\x00\x03\x00\x11\x01\x00\x00\xE2\x01\x00\x00" +"\xF9\x00\x02\x00\xD8\x01\x00\x00\xF8\x00\x02\x00\xD8\x01\x00\x00\x3D\x00\x04\x00\x0D\x00\x00\x00\xE3\x01\x00\x00\x11\x01\x00\x00" +"\x41\x00\x05\x00\x5F\x00\x00\x00\xE5\x01\x00\x00\x30\x00\x00\x00\xE4\x01\x00\x00\x3D\x00\x04\x00\x0D\x00\x00\x00\xE6\x01\x00\x00" +"\xE5\x01\x00\x00\x85\x00\x05\x00\x0D\x00\x00\x00\xE7\x01\x00\x00\xE3\x01\x00\x00\xE6\x01\x00\x00\x3E\x00\x03\x00\x11\x01\x00\x00" +"\xE7\x01\x00\x00\xB6\x00\x05\x00\x21\x00\x00\x00\xE9\x01\x00\x00\xE8\x01\x00\x00\x54\x00\x00\x00\xF7\x00\x03\x00\xEB\x01\x00\x00" +"\x00\x00\x00\x00\xFA\x00\x04\x00\xE9\x01\x00\x00\xEA\x01\x00\x00\xEB\x01\x00\x00\xF8\x00\x02\x00\xEA\x01\x00\x00\xF7\x00\x03\x00" +"\xEF\x01\x00\x00\x00\x00\x00\x00\xFA\x00\x04\x00\xED\x01\x00\x00\xEE\x01\x00\x00\xF7\x01\x00\x00\xF8\x00\x02\x00\xEE\x01\x00\x00" +"\x41\x00\x05\x00\xF0\x01\x00\x00\xF1\x01\x00\x00\x11\x01\x00\x00\x3C\x00\x00\x00\x3D\x00\x04\x00\x06\x00\x00\x00\xF2\x01\x00\x00" +"\xF1\x01\x00\x00\xB8\x00\x05\x00\x21\x00\x00\x00\xF3\x01\x00\x00\xF2\x01\x00\x00\xE8\x01\x00\x00\xF7\x00\x03\x00\xF5\x01\x00\x00" +"\x00\x00\x00\x00\xFA\x00\x04\x00\xF3\x01\x00\x00\xF4\x01\x00\x00\xF5\x01\x00\x00\xF8\x00\x02\x00\xF4\x01\x00\x00\xFC\x00\x01\x00" +"\xF8\x00\x02\x00\xF5\x01\x00\x00\xF9\x00\x02\x00\xEF\x01\x00\x00\xF8\x00\x02\x00\xF7\x01\x00\x00\x41\x00\x05\x00\xF0\x01\x00\x00" +"\xF8\x01\x00\x00\x11\x01\x00\x00\x3C\x00\x00\x00\x3D\x00\x04\x00\x06\x00\x00\x00\xF9\x01\x00\x00\xF8\x01\x00\x00\xBE\x00\x05\x00" +"\x21\x00\x00\x00\xFA\x01\x00\x00\xF9\x01\x00\x00\xE8\x01\x00\x00\xF7\x00\x03\x00\xFC\x01\x00\x00\x00\x00\x00\x00\xFA\x00\x04\x00" +"\xFA\x01\x00\x00\xFB\x01\x00\x00\xFC\x01\x00\x00\xF8\x00\x02\x00\xFB\x01\x00\x00\xFC\x00\x01\x00\xF8\x00\x02\x00\xFC\x01\x00\x00" +"\xF9\x00\x02\x00\xEF\x01\x00\x00\xF8\x00\x02\x00\xEF\x01\x00\x00\x41\x00\x05\x00\xF0\x01\x00\x00\xFE\x01\x00\x00\x11\x01\x00\x00" +"\x3C\x00\x00\x00\x3E\x00\x03\x00\xFE\x01\x00\x00\x54\x00\x00\x00\xF9\x00\x02\x00\xEB\x01\x00\x00\xF8\x00\x02\x00\xEB\x01\x00\x00" +"\x3D\x00\x04\x00\x0D\x00\x00\x00\x00\x02\x00\x00\x11\x01\x00\x00\x3E\x00\x03\x00\xFF\x01\x00\x00\x00\x02\x00\x00\x39\x00\x05\x00" +"\x0D\x00\x00\x00\x01\x02\x00\x00\x11\x00\x00\x00\xFF\x01\x00\x00\x3E\x00\x03\x00\x11\x01\x00\x00\x01\x02\x00\x00\xFD\x00\x01\x00" +"\x38\x00\x01\x00\x36\x00\x05\x00\x07\x00\x00\x00\x0B\x00\x00\x00\x00\x00\x00\x00\x09\x00\x00\x00\x37\x00\x03\x00\x08\x00\x00\x00" +"\x0A\x00\x00\x00\xF8\x00\x02\x00\x0C\x00\x00\x00\x3B\x00\x04\x00\x28\x00\x00\x00\x29\x00\x00\x00\x07\x00\x00\x00\x3B\x00\x04\x00" +"\x28\x00\x00\x00\x4E\x00\x00\x00\x07\x00\x00\x00\xF7\x00\x03\x00\x25\x00\x00\x00\x00\x00\x00\x00\xFA\x00\x04\x00\x23\x00\x00\x00" +"\x24\x00\x00\x00\x25\x00\x00\x00\xF8\x00\x02\x00\x24\x00\x00\x00\x3D\x00\x04\x00\x07\x00\x00\x00\x26\x00\x00\x00\x0A\x00\x00\x00" +"\xFE\x00\x02\x00\x26\x00\x00\x00\xF8\x00\x02\x00\x25\x00\x00\x00\x41\x00\x05\x00\x32\x00\x00\x00\x33\x00\x00\x00\x30\x00\x00\x00" +"\x31\x00\x00\x00\x3D\x00\x04\x00\x06\x00\x00\x00\x34\x00\x00\x00\x33\x00\x00\x00\x41\x00\x05\x00\x38\x00\x00\x00\x39\x00\x00\x00" +"\x36\x00\x00\x00\x37\x00\x00\x00\x3D\x00\x04\x00\x06\x00\x00\x00\x3A\x00\x00\x00\x39\x00\x00\x00\x85\x00\x05\x00\x06\x00\x00\x00" +"\x3B\x00\x00\x00\x34\x00\x00\x00\x3A\x00\x00\x00\x41\x00\x05\x00\x38\x00\x00\x00\x3D\x00\x00\x00\x36\x00\x00\x00\x3C\x00\x00\x00" +"\x3D\x00\x04\x00\x06\x00\x00\x00\x3E\x00\x00\x00\x3D\x00\x00\x00\x88\x00\x05\x00\x06\x00\x00\x00\x3F\x00\x00\x00\x3B\x00\x00\x00" +"\x3E\x00\x00\x00\x3E\x00\x03\x00\x29\x00\x00\x00\x3F\x00\x00\x00\x3D\x00\x04\x00\x06\x00\x00\x00\x41\x00\x00\x00\x29\x00\x00\x00" +"\x41\x00\x05\x00\x32\x00\x00\x00\x43\x00\x00\x00\x30\x00\x00\x00\x42\x00\x00\x00\x3D\x00\x04\x00\x06\x00\x00\x00\x44\x00\x00\x00" +"\x43\x00\x00\x00\x83\x00\x05\x00\x06\x00\x00\x00\x45\x00\x00\x00\x41\x00\x00\x00\x44\x00\x00\x00\x0C\x00\x07\x00\x06\x00\x00\x00" +"\x46\x00\x00\x00\x01\x00\x00\x00\x28\x00\x00\x00\x40\x00\x00\x00\x45\x00\x00\x00\x3E\x00\x03\x00\x29\x00\x00\x00\x46\x00\x00\x00" +"\xF7\x00\x03\x00\x4A\x00\x00\x00\x00\x00\x00\x00\xFA\x00\x04\x00\x48\x00\x00\x00\x49\x00\x00\x00\x4A\x00\x00\x00\xF8\x00\x02\x00" +"\x49\x00\x00\x00\x3D\x00\x04\x00\x06\x00\x00\x00\x4B\x00\x00\x00\x29\x00\x00\x00\x3D\x00\x04\x00\x06\x00\x00\x00\x4C\x00\x00\x00" +"\x29\x00\x00\x00\x85\x00\x05\x00\x06\x00\x00\x00\x4D\x00\x00\x00\x4C\x00\x00\x00\x4B\x00\x00\x00\x3E\x00\x03\x00\x29\x00\x00\x00" +"\x4D\x00\x00\x00\xF9\x00\x02\x00\x4A\x00\x00\x00\xF8\x00\x02\x00\x4A\x00\x00\x00\x3D\x00\x04\x00\x06\x00\x00\x00\x4F\x00\x00\x00" +"\x29\x00\x00\x00\x85\x00\x05\x00\x06\x00\x00\x00\x51\x00\x00\x00\x4F\x00\x00\x00\x50\x00\x00\x00\x7F\x00\x04\x00\x06\x00\x00\x00" +"\x52\x00\x00\x00\x51\x00\x00\x00\x0C\x00\x06\x00\x06\x00\x00\x00\x53\x00\x00\x00\x01\x00\x00\x00\x1D\x00\x00\x00\x52\x00\x00\x00" +"\x3E\x00\x03\x00\x4E\x00\x00\x00\x53\x00\x00\x00\x41\x00\x06\x00\x32\x00\x00\x00\x56\x00\x00\x00\x30\x00\x00\x00\x55\x00\x00\x00" +"\x3C\x00\x00\x00\x3D\x00\x04\x00\x06\x00\x00\x00\x57\x00\x00\x00\x56\x00\x00\x00\x83\x00\x05\x00\x06\x00\x00\x00\x58\x00\x00\x00" +"\x54\x00\x00\x00\x57\x00\x00\x00\x3D\x00\x04\x00\x06\x00\x00\x00\x59\x00\x00\x00\x4E\x00\x00\x00\x0C\x00\x08\x00\x06\x00\x00\x00" +"\x5A\x00\x00\x00\x01\x00\x00\x00\x2B\x00\x00\x00\x59\x00\x00\x00\x40\x00\x00\x00\x54\x00\x00\x00\x41\x00\x06\x00\x32\x00\x00\x00" +"\x5B\x00\x00\x00\x30\x00\x00\x00\x55\x00\x00\x00\x3C\x00\x00\x00\x3D\x00\x04\x00\x06\x00\x00\x00\x5C\x00\x00\x00\x5B\x00\x00\x00" +"\x85\x00\x05\x00\x06\x00\x00\x00\x5D\x00\x00\x00\x5A\x00\x00\x00\x5C\x00\x00\x00\x81\x00\x05\x00\x06\x00\x00\x00\x5E\x00\x00\x00" +"\x58\x00\x00\x00\x5D\x00\x00\x00\x3E\x00\x03\x00\x4E\x00\x00\x00\x5E\x00\x00\x00\x41\x00\x05\x00\x5F\x00\x00\x00\x60\x00\x00\x00" +"\x30\x00\x00\x00\x55\x00\x00\x00\x3D\x00\x04\x00\x0D\x00\x00\x00\x61\x00\x00\x00\x60\x00\x00\x00\x4F\x00\x08\x00\x07\x00\x00\x00" +"\x62\x00\x00\x00\x61\x00\x00\x00\x61\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x02\x00\x00\x00\x3D\x00\x04\x00\x07\x00\x00\x00" +"\x63\x00\x00\x00\x0A\x00\x00\x00\x3D\x00\x04\x00\x06\x00\x00\x00\x64\x00\x00\x00\x4E\x00\x00\x00\x50\x00\x06\x00\x07\x00\x00\x00" +"\x65\x00\x00\x00\x64\x00\x00\x00\x64\x00\x00\x00\x64\x00\x00\x00\x0C\x00\x08\x00\x07\x00\x00\x00\x66\x00\x00\x00\x01\x00\x00\x00" +"\x2E\x00\x00\x00\x62\x00\x00\x00\x63\x00\x00\x00\x65\x00\x00\x00\xFE\x00\x02\x00\x66\x00\x00\x00\x38\x00\x01\x00\x36\x00\x05\x00" +"\x0D\x00\x00\x00\x11\x00\x00\x00\x00\x00\x00\x00\x0F\x00\x00\x00\x37\x00\x03\x00\x0E\x00\x00\x00\x10\x00\x00\x00\xF8\x00\x02\x00" +"\x12\x00\x00\x00\x3B\x00\x04\x00\x08\x00\x00\x00\x6F\x00\x00\x00\x07\x00\x00\x00\xF7\x00\x03\x00\x6C\x00\x00\x00\x00\x00\x00\x00" +"\xFA\x00\x04\x00\x6A\x00\x00\x00\x6B\x00\x00\x00\x6C\x00\x00\x00\xF8\x00\x02\x00\x6B\x00\x00\x00\x3D\x00\x04\x00\x0D\x00\x00\x00" +"\x6D\x00\x00\x00\x10\x00\x00\x00\xFE\x00\x02\x00\x6D\x00\x00\x00\xF8\x00\x02\x00\x6C\x00\x00\x00\x3D\x00\x04\x00\x0D\x00\x00\x00" +"\x70\x00\x00\x00\x10\x00\x00\x00\x4F\x00\x08\x00\x07\x00\x00\x00\x71\x00\x00\x00\x70\x00\x00\x00\x70\x00\x00\x00\x00\x00\x00\x00" +"\x01\x00\x00\x00\x02\x00\x00\x00\x3E\x00\x03\x00\x6F\x00\x00\x00\x71\x00\x00\x00\x39\x00\x05\x00\x07\x00\x00\x00\x72\x00\x00\x00" +"\x0B\x00\x00\x00\x6F\x00\x00\x00\x51\x00\x05\x00\x06\x00\x00\x00\x73\x00\x00\x00\x72\x00\x00\x00\x00\x00\x00\x00\x51\x00\x05\x00" +"\x06\x00\x00\x00\x74\x00\x00\x00\x72\x00\x00\x00\x01\x00\x00\x00\x51\x00\x05\x00\x06\x00\x00\x00\x75\x00\x00\x00\x72\x00\x00\x00" +"\x02\x00\x00\x00\x50\x00\x07\x00\x0D\x00\x00\x00\x76\x00\x00\x00\x73\x00\x00\x00\x74\x00\x00\x00\x75\x00\x00\x00\x54\x00\x00\x00" +"\x41\x00\x05\x00\x28\x00\x00\x00\x77\x00\x00\x00\x10\x00\x00\x00\x3C\x00\x00\x00\x3D\x00\x04\x00\x06\x00\x00\x00\x78\x00\x00\x00" +"\x77\x00\x00\x00\x8E\x00\x05\x00\x0D\x00\x00\x00\x79\x00\x00\x00\x76\x00\x00\x00\x78\x00\x00\x00\xFE\x00\x02\x00\x79\x00\x00\x00" +"\x38\x00\x01\x00\x36\x00\x05\x00\x16\x00\x00\x00\x1C\x00\x00\x00\x00\x00\x00\x00\x18\x00\x00\x00\x37\x00\x03\x00\x15\x00\x00\x00" +"\x19\x00\x00\x00\x37\x00\x03\x00\x17\x00\x00\x00\x1A\x00\x00\x00\x37\x00\x03\x00\x08\x00\x00\x00\x1B\x00\x00\x00\xF8\x00\x02\x00" +"\x1D\x00\x00\x00\x3B\x00\x04\x00\x08\x00\x00\x00\x7F\x00\x00\x00\x07\x00\x00\x00\x3B\x00\x04\x00\x08\x00\x00\x00\x8C\x00\x00\x00" +"\x07\x00\x00\x00\x3B\x00\x04\x00\x28\x00\x00\x00\x98\x00\x00\x00\x07\x00\x00\x00\x3B\x00\x04\x00\x28\x00\x00\x00\xAE\x00\x00\x00" +"\x07\x00\x00\x00\x3B\x00\x04\x00\x17\x00\x00\x00\xD5\x00\x00\x00\x07\x00\x00\x00\x3B\x00\x04\x00\x17\x00\x00\x00\xDC\x00\x00\x00" +"\x07\x00\x00\x00\xF7\x00\x03\x00\x7E\x00\x00\x00\x00\x00\x00\x00\xFA\x00\x04\x00\x7C\x00\x00\x00\x7D\x00\x00\x00\xD0\x00\x00\x00" +"\xF8\x00\x02\x00\x7D\x00\x00\x00\x3D\x00\x04\x00\x07\x00\x00\x00\x80\x00\x00\x00\x1B\x00\x00\x00\x0C\x00\x06\x00\x07\x00\x00\x00" +"\x81\x00\x00\x00\x01\x00\x00\x00\x45\x00\x00\x00\x80\x00\x00\x00\x4F\x00\x07\x00\x16\x00\x00\x00\x82\x00\x00\x00\x81\x00\x00\x00" +"\x81\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x8E\x00\x05\x00\x16\x00\x00\x00\x84\x00\x00\x00\x82\x00\x00\x00\x83\x00\x00\x00" +"\x8E\x00\x05\x00\x16\x00\x00\x00\x85\x00\x00\x00\x84\x00\x00\x00\x54\x00\x00\x00\x85\x00\x05\x00\x16\x00\x00\x00\x88\x00\x00\x00" +"\x85\x00\x00\x00\x87\x00\x00\x00\x51\x00\x05\x00\x06\x00\x00\x00\x89\x00\x00\x00\x88\x00\x00\x00\x00\x00\x00\x00\x51\x00\x05\x00" +"\x06\x00\x00\x00\x8A\x00\x00\x00\x88\x00\x00\x00\x01\x00\x00\x00\x50\x00\x06\x00\x07\x00\x00\x00\x8B\x00\x00\x00\x89\x00\x00\x00" +"\x8A\x00\x00\x00\x86\x00\x00\x00\x3E\x00\x03\x00\x7F\x00\x00\x00\x8B\x00\x00\x00\x3D\x00\x04\x00\x16\x00\x00\x00\x8D\x00\x00\x00" +"\x1A\x00\x00\x00\x51\x00\x05\x00\x06\x00\x00\x00\x8E\x00\x00\x00\x8D\x00\x00\x00\x00\x00\x00\x00\x51\x00\x05\x00\x06\x00\x00\x00" +"\x8F\x00\x00\x00\x8D\x00\x00\x00\x01\x00\x00\x00\x50\x00\x05\x00\x16\x00\x00\x00\x90\x00\x00\x00\x8E\x00\x00\x00\x8F\x00\x00\x00" +"\x51\x00\x05\x00\x06\x00\x00\x00\x91\x00\x00\x00\x90\x00\x00\x00\x00\x00\x00\x00\x51\x00\x05\x00\x06\x00\x00\x00\x92\x00\x00\x00" +"\x90\x00\x00\x00\x01\x00\x00\x00\x50\x00\x06\x00\x07\x00\x00\x00\x93\x00\x00\x00\x91\x00\x00\x00\x92\x00\x00\x00\x54\x00\x00\x00" +"\x3E\x00\x03\x00\x8C\x00\x00\x00\x93\x00\x00\x00\x3D\x00\x04\x00\x07\x00\x00\x00\x95\x00\x00\x00\x7F\x00\x00\x00\x50\x00\x06\x00" +"\x07\x00\x00\x00\x96\x00\x00\x00\x94\x00\x00\x00\x94\x00\x00\x00\x94\x00\x00\x00\x88\x00\x05\x00\x07\x00\x00\x00\x97\x00\x00\x00" +"\x95\x00\x00\x00\x96\x00\x00\x00\x3E\x00\x03\x00\x7F\x00\x00\x00\x97\x00\x00\x00\x3E\x00\x03\x00\x98\x00\x00\x00\x54\x00\x00\x00" +"\xF9\x00\x02\x00\x99\x00\x00\x00\xF8\x00\x02\x00\x99\x00\x00\x00\xF6\x00\x04\x00\x9B\x00\x00\x00\x9C\x00\x00\x00\x00\x00\x00\x00" +"\xF9\x00\x02\x00\x9D\x00\x00\x00\xF8\x00\x02\x00\x9D\x00\x00\x00\x3D\x00\x04\x00\x06\x00\x00\x00\x9E\x00\x00\x00\x98\x00\x00\x00" +"\xB8\x00\x05\x00\x21\x00\x00\x00\x9F\x00\x00\x00\x9E\x00\x00\x00\x94\x00\x00\x00\xFA\x00\x04\x00\x9F\x00\x00\x00\x9A\x00\x00\x00" +"\x9B\x00\x00\x00\xF8\x00\x02\x00\x9A\x00\x00\x00\x3D\x00\x04\x00\x07\x00\x00\x00\xA0\x00\x00\x00\x7F\x00\x00\x00\x3D\x00\x04\x00" +"\x14\x00\x00\x00\xA1\x00\x00\x00\x19\x00\x00\x00\x3D\x00\x04\x00\x07\x00\x00\x00\xA2\x00\x00\x00\x8C\x00\x00\x00\x4F\x00\x07\x00" +"\x16\x00\x00\x00\xA3\x00\x00\x00\xA2\x00\x00\x00\xA2\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x57\x00\x05\x00\x0D\x00\x00\x00" +"\xA4\x00\x00\x00\xA1\x00\x00\x00\xA3\x00\x00\x00\x51\x00\x05\x00\x06\x00\x00\x00\xA5\x00\x00\x00\xA4\x00\x00\x00\x03\x00\x00\x00" +"\x41\x00\x05\x00\x28\x00\x00\x00\xA6\x00\x00\x00\x8C\x00\x00\x00\x37\x00\x00\x00\x3D\x00\x04\x00\x06\x00\x00\x00\xA7\x00\x00\x00" +"\xA6\x00\x00\x00\x0C\x00\x07\x00\x06\x00\x00\x00\xA8\x00\x00\x00\x01\x00\x00\x00\x30\x00\x00\x00\xA5\x00\x00\x00\xA7\x00\x00\x00" +"\x8E\x00\x05\x00\x07\x00\x00\x00\xA9\x00\x00\x00\xA0\x00\x00\x00\xA8\x00\x00\x00\x3D\x00\x04\x00\x07\x00\x00\x00\xAA\x00\x00\x00" +"\x8C\x00\x00\x00\x81\x00\x05\x00\x07\x00\x00\x00\xAB\x00\x00\x00\xAA\x00\x00\x00\xA9\x00\x00\x00\x3E\x00\x03\x00\x8C\x00\x00\x00" +"\xAB\x00\x00\x00\xF9\x00\x02\x00\x9C\x00\x00\x00\xF8\x00\x02\x00\x9C\x00\x00\x00\x3D\x00\x04\x00\x06\x00\x00\x00\xAC\x00\x00\x00" +"\x98\x00\x00\x00\x81\x00\x05\x00\x06\x00\x00\x00\xAD\x00\x00\x00\xAC\x00\x00\x00\x54\x00\x00\x00\x3E\x00\x03\x00\x98\x00\x00\x00" +"\xAD\x00\x00\x00\xF9\x00\x02\x00\x99\x00\x00\x00\xF8\x00\x02\x00\x9B\x00\x00\x00\x3E\x00\x03\x00\x98\x00\x00\x00\x40\x00\x00\x00" +"\x3E\x00\x03\x00\xAE\x00\x00\x00\x54\x00\x00\x00\xF9\x00\x02\x00\xAF\x00\x00\x00\xF8\x00\x02\x00\xAF\x00\x00\x00\xF6\x00\x04\x00" +"\xB1\x00\x00\x00\xB2\x00\x00\x00\x00\x00\x00\x00\xF9\x00\x02\x00\xB3\x00\x00\x00\xF8\x00\x02\x00\xB3\x00\x00\x00\x3D\x00\x04\x00" +"\x06\x00\x00\x00\xB4\x00\x00\x00\x98\x00\x00\x00\xB8\x00\x05\x00\x21\x00\x00\x00\xB6\x00\x00\x00\xB4\x00\x00\x00\xB5\x00\x00\x00" +"\xFA\x00\x04\x00\xB6\x00\x00\x00\xB0\x00\x00\x00\xB1\x00\x00\x00\xF8\x00\x02\x00\xB0\x00\x00\x00\x3D\x00\x04\x00\x07\x00\x00\x00" +"\xB7\x00\x00\x00\x7F\x00\x00\x00\x3D\x00\x04\x00\x14\x00\x00\x00\xB8\x00\x00\x00\x19\x00\x00\x00\x3D\x00\x04\x00\x07\x00\x00\x00" +"\xB9\x00\x00\x00\x8C\x00\x00\x00\x4F\x00\x07\x00\x16\x00\x00\x00\xBA\x00\x00\x00\xB9\x00\x00\x00\xB9\x00\x00\x00\x00\x00\x00\x00" +"\x01\x00\x00\x00\x57\x00\x05\x00\x0D\x00\x00\x00\xBB\x00\x00\x00\xB8\x00\x00\x00\xBA\x00\x00\x00\x51\x00\x05\x00\x06\x00\x00\x00" +"\xBC\x00\x00\x00\xBB\x00\x00\x00\x03\x00\x00\x00\x41\x00\x05\x00\x28\x00\x00\x00\xBD\x00\x00\x00\x8C\x00\x00\x00\x37\x00\x00\x00" +"\x3D\x00\x04\x00\x06\x00\x00\x00\xBE\x00\x00\x00\xBD\x00\x00\x00\x0C\x00\x07\x00\x06\x00\x00\x00\xBF\x00\x00\x00\x01\x00\x00\x00" +"\x30\x00\x00\x00\xBC\x00\x00\x00\xBE\x00\x00\x00\x3D\x00\x04\x00\x06\x00\x00\x00\xC0\x00\x00\x00\xAE\x00\x00\x00\x85\x00\x05\x00" +"\x06\x00\x00\x00\xC1\x00\x00\x00\xBF\x00\x00\x00\xC0\x00\x00\x00\x3D\x00\x04\x00\x06\x00\x00\x00\xC3\x00\x00\x00\xAE\x00\x00\x00" +"\x85\x00\x05\x00\x06\x00\x00\x00\xC4\x00\x00\x00\xC2\x00\x00\x00\xC3\x00\x00\x00\x83\x00\x05\x00\x06\x00\x00\x00\xC5\x00\x00\x00" +"\xC1\x00\x00\x00\xC4\x00\x00\x00\x8E\x00\x05\x00\x07\x00\x00\x00\xC6\x00\x00\x00\xB7\x00\x00\x00\xC5\x00\x00\x00\x3D\x00\x04\x00" +"\x07\x00\x00\x00\xC7\x00\x00\x00\x8C\x00\x00\x00\x81\x00\x05\x00\x07\x00\x00\x00\xC8\x00\x00\x00\xC7\x00\x00\x00\xC6\x00\x00\x00" +"\x3E\x00\x03\x00\x8C\x00\x00\x00\xC8\x00\x00\x00\xF9\x00\x02\x00\xB2\x00\x00\x00\xF8\x00\x02\x00\xB2\x00\x00\x00\x3D\x00\x04\x00" +"\x06\x00\x00\x00\xC9\x00\x00\x00\x98\x00\x00\x00\x81\x00\x05\x00\x06\x00\x00\x00\xCA\x00\x00\x00\xC9\x00\x00\x00\x54\x00\x00\x00" +"\x3E\x00\x03\x00\x98\x00\x00\x00\xCA\x00\x00\x00\x3D\x00\x04\x00\x06\x00\x00\x00\xCB\x00\x00\x00\xAE\x00\x00\x00\x85\x00\x05\x00" +"\x06\x00\x00\x00\xCC\x00\x00\x00\xCB\x00\x00\x00\xC2\x00\x00\x00\x3E\x00\x03\x00\xAE\x00\x00\x00\xCC\x00\x00\x00\xF9\x00\x02\x00" +"\xAF\x00\x00\x00\xF8\x00\x02\x00\xB1\x00\x00\x00\x3D\x00\x04\x00\x07\x00\x00\x00\xCD\x00\x00\x00\x8C\x00\x00\x00\x4F\x00\x07\x00" +"\x16\x00\x00\x00\xCE\x00\x00\x00\xCD\x00\x00\x00\xCD\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\xFE\x00\x02\x00\xCE\x00\x00\x00" +"\xF8\x00\x02\x00\xD0\x00\x00\x00\xBA\x00\x05\x00\x21\x00\x00\x00\xD2\x00\x00\x00\xD1\x00\x00\x00\x40\x00\x00\x00\xF7\x00\x03\x00" +"\xD4\x00\x00\x00\x00\x00\x00\x00\xFA\x00\x04\x00\xD2\x00\x00\x00\xD3\x00\x00\x00\xD4\x00\x00\x00\xF8\x00\x02\x00\xD3\x00\x00\x00" +"\x3D\x00\x04\x00\x07\x00\x00\x00\xD6\x00\x00\x00\x1B\x00\x00\x00\x0C\x00\x06\x00\x07\x00\x00\x00\xD7\x00\x00\x00\x01\x00\x00\x00" +"\x45\x00\x00\x00\xD6\x00\x00\x00\x4F\x00\x07\x00\x16\x00\x00\x00\xD8\x00\x00\x00\xD7\x00\x00\x00\xD7\x00\x00\x00\x00\x00\x00\x00" +"\x01\x00\x00\x00\x8E\x00\x05\x00\x16\x00\x00\x00\xD9\x00\x00\x00\xD8\x00\x00\x00\x83\x00\x00\x00\x8E\x00\x05\x00\x16\x00\x00\x00" +"\xDA\x00\x00\x00\xD9\x00\x00\x00\x54\x00\x00\x00\x85\x00\x05\x00\x16\x00\x00\x00\xDB\x00\x00\x00\xDA\x00\x00\x00\x87\x00\x00\x00" +"\x3E\x00\x03\x00\xD5\x00\x00\x00\xDB\x00\x00\x00\x3D\x00\x04\x00\x16\x00\x00\x00\xDD\x00\x00\x00\x1A\x00\x00\x00\x3E\x00\x03\x00" +"\xDC\x00\x00\x00\xDD\x00\x00\x00\x3D\x00\x04\x00\x16\x00\x00\x00\xDE\x00\x00\x00\xD5\x00\x00\x00\x3D\x00\x04\x00\x16\x00\x00\x00" +"\xDF\x00\x00\x00\xDC\x00\x00\x00\x81\x00\x05\x00\x16\x00\x00\x00\xE0\x00\x00\x00\xDF\x00\x00\x00\xDE\x00\x00\x00\x3E\x00\x03\x00" +"\xDC\x00\x00\x00\xE0\x00\x00\x00\x3D\x00\x04\x00\x16\x00\x00\x00\xE2\x00\x00\x00\xD5\x00\x00\x00\x8E\x00\x05\x00\x16\x00\x00\x00" +"\xE3\x00\x00\x00\xE2\x00\x00\x00\xE1\x00\x00\x00\x3E\x00\x03\x00\xD5\x00\x00\x00\xE3\x00\x00\x00\x3D\x00\x04\x00\x16\x00\x00\x00" +"\xE4\x00\x00\x00\xD5\x00\x00\x00\x3D\x00\x04\x00\x14\x00\x00\x00\xE5\x00\x00\x00\x19\x00\x00\x00\x3D\x00\x04\x00\x16\x00\x00\x00" +"\xE6\x00\x00\x00\xDC\x00\x00\x00\x57\x00\x05\x00\x0D\x00\x00\x00\xE7\x00\x00\x00\xE5\x00\x00\x00\xE6\x00\x00\x00\x51\x00\x05\x00" +"\x06\x00\x00\x00\xE8\x00\x00\x00\xE7\x00\x00\x00\x03\x00\x00\x00\x8E\x00\x05\x00\x16\x00\x00\x00\xE9\x00\x00\x00\xE4\x00\x00\x00" +"\xE8\x00\x00\x00\x3D\x00\x04\x00\x16\x00\x00\x00\xEA\x00\x00\x00\xDC\x00\x00\x00\x83\x00\x05\x00\x16\x00\x00\x00\xEB\x00\x00\x00" +"\xEA\x00\x00\x00\xE9\x00\x00\x00\x3E\x00\x03\x00\xDC\x00\x00\x00\xEB\x00\x00\x00\x3D\x00\x04\x00\x16\x00\x00\x00\xEC\x00\x00\x00" +"\xD5\x00\x00\x00\x3D\x00\x04\x00\x14\x00\x00\x00\xED\x00\x00\x00\x19\x00\x00\x00\x3D\x00\x04\x00\x16\x00\x00\x00\xEE\x00\x00\x00" +"\xDC\x00\x00\x00\x57\x00\x05\x00\x0D\x00\x00\x00\xEF\x00\x00\x00\xED\x00\x00\x00\xEE\x00\x00\x00\x51\x00\x05\x00\x06\x00\x00\x00" +"\xF0\x00\x00\x00\xEF\x00\x00\x00\x03\x00\x00\x00\x8E\x00\x05\x00\x16\x00\x00\x00\xF1\x00\x00\x00\xEC\x00\x00\x00\xF0\x00\x00\x00" +"\x3D\x00\x04\x00\x16\x00\x00\x00\xF2\x00\x00\x00\xDC\x00\x00\x00\x83\x00\x05\x00\x16\x00\x00\x00\xF3\x00\x00\x00\xF2\x00\x00\x00" +"\xF1\x00\x00\x00\x3E\x00\x03\x00\xDC\x00\x00\x00\xF3\x00\x00\x00\x3D\x00\x04\x00\x16\x00\x00\x00\xF4\x00\x00\x00\xD5\x00\x00\x00" +"\x3D\x00\x04\x00\x14\x00\x00\x00\xF5\x00\x00\x00\x19\x00\x00\x00\x3D\x00\x04\x00\x16\x00\x00\x00\xF6\x00\x00\x00\xDC\x00\x00\x00" +"\x57\x00\x05\x00\x0D\x00\x00\x00\xF7\x00\x00\x00\xF5\x00\x00\x00\xF6\x00\x00\x00\x51\x00\x05\x00\x06\x00\x00\x00\xF8\x00\x00\x00" +"\xF7\x00\x00\x00\x03\x00\x00\x00\x8E\x00\x05\x00\x16\x00\x00\x00\xF9\x00\x00\x00\xF4\x00\x00\x00\xF8\x00\x00\x00\x3D\x00\x04\x00" +"\x16\x00\x00\x00\xFA\x00\x00\x00\xDC\x00\x00\x00\x83\x00\x05\x00\x16\x00\x00\x00\xFB\x00\x00\x00\xFA\x00\x00\x00\xF9\x00\x00\x00" +"\x3E\x00\x03\x00\xDC\x00\x00\x00\xFB\x00\x00\x00\x3D\x00\x04\x00\x16\x00\x00\x00\xFC\x00\x00\x00\xDC\x00\x00\x00\xFE\x00\x02\x00" +"\xFC\x00\x00\x00\xF8\x00\x02\x00\xD4\x00\x00\x00\xF9\x00\x02\x00\x7E\x00\x00\x00\xF8\x00\x02\x00\x7E\x00\x00\x00\x3D\x00\x04\x00" +"\x16\x00\x00\x00\xFE\x00\x00\x00\x1A\x00\x00\x00\xFE\x00\x02\x00\xFE\x00\x00\x00\x38\x00\x01\x00"}, #endif #ifdef D3D9QUAKE {QR_DIRECT3D9, 9, "defaultwall", diff --git a/engine/gl/shader.h b/engine/gl/shader.h index 1b8fc4767..2d4e2c785 100644 --- a/engine/gl/shader.h +++ b/engine/gl/shader.h @@ -542,6 +542,12 @@ typedef struct programshared_s unsigned int supportedpermutations; unsigned char *cvardata; unsigned int cvardatasize; + int shaderver; //glsl version + char *preshade; //general prefixed #defines + char *shadertext; //the glsl text + unsigned char failed[(PERMUTATIONS+7)/8]; //so we don't try recompiling endlessly + struct programpermu_s *permu[PERMUTATIONS]; //set once compiled. + #ifdef VKQUAKE qVkShaderModule vert; //for slightly faster regeneration qVkShaderModule frag; @@ -549,14 +555,6 @@ typedef struct programshared_s qVkDescriptorSetLayout desclayout; struct pipeline_s *pipelines; #endif -#define DELAYEDSHADERCOMPILE -#ifdef DELAYEDSHADERCOMPILE - int shaderver; //glsl version - char *preshade; //general prefixed #defines - char *shadertext; //the glsl text - unsigned char failed[(PERMUTATIONS+7)/8]; //so we don't try recompiling endlessly - struct programpermu_s *permu[PERMUTATIONS]; //set once compiled. -#endif } program_t; typedef struct { @@ -798,6 +796,7 @@ typedef struct unsigned int maxver; //highest glsl version usable unsigned int max_gpu_bones; //max number of bones supported by uniforms. + int hw_bc, hw_etc, hw_astc; //these are set only if the hardware actually supports the format, and not if we think the drivers are software-decoding them (unlike texfmt). qboolean texfmt[PTI_MAX]; //which texture formats are supported (renderable not implied) unsigned int texture2d_maxsize; //max size of a 2d texture unsigned int texture3d_maxsize; //max size of a 3d texture @@ -812,6 +811,7 @@ typedef struct qboolean env_add; qboolean can_mipcap; //gl1.2+ qboolean can_mipbias; //gl1.4+ + qboolean can_genmips; //gl3.0+ qboolean havecubemaps; //since gl1.3, so pretty much everyone will have this... should probably only be set if we also have seamless or clamp-to-edge. void (*pDeleteProg) (program_t *prog); @@ -841,6 +841,7 @@ extern const struct sh_defaultsamplers_s #ifdef VKQUAKE qboolean VK_LoadBlob(program_t *prog, void *blobdata, const char *name); +void VK_RegisterVulkanCvars(void); #endif #ifdef GLQUAKE diff --git a/engine/qclib/pr_edict.c b/engine/qclib/pr_edict.c index f5e6be7f4..621191923 100644 --- a/engine/qclib/pr_edict.c +++ b/engine/qclib/pr_edict.c @@ -2743,7 +2743,7 @@ retry: if (!trysleft) //the progs exists, let's just be happy about it. externs->Printf("Progs is out of date and uncompilable\n"); - if (externs->CheckHeaderCrc && !externs->CheckHeaderCrc(&progfuncs->funcs, prinst.pr_typecurrent, pr_progs->crc)) + if (externs->CheckHeaderCrc && !externs->CheckHeaderCrc(&progfuncs->funcs, prinst.pr_typecurrent, pr_progs->crc, filename)) { // externs->Printf ("%s system vars have been modified, progdefs.h is out of date\n", filename); PRHunkFree(progfuncs, hmark); diff --git a/engine/qclib/progslib.h b/engine/qclib/progslib.h index fc3e1f31d..ddcf03257 100644 --- a/engine/qclib/progslib.h +++ b/engine/qclib/progslib.h @@ -212,7 +212,7 @@ typedef struct progexterns_s { int (VARGS *DPrintf) (const char *, ...) LIKEPRINTF(1); void (VARGS *Sys_Error) (const char *, ...) LIKEPRINTF(1); void (VARGS *Abort) (char *, ...) LIKEPRINTF(1); - pbool (PDECL *CheckHeaderCrc) (pubprogfuncs_t *inst, progsnum_t idx, int crc); + pbool (PDECL *CheckHeaderCrc) (pubprogfuncs_t *inst, progsnum_t idx, int crc, const char *filename); void (PDECL *entspawn) (struct edict_s *ent, int loading); //ent has been spawned, but may not have all the extra variables (that may need to be set) set pbool (PDECL *entcanfree) (struct edict_s *ent); //return true to stop ent from being freed diff --git a/engine/server/pr_cmds.c b/engine/server/pr_cmds.c index 70d6afd87..902eeb936 100644 --- a/engine/server/pr_cmds.c +++ b/engine/server/pr_cmds.c @@ -711,7 +711,7 @@ static qboolean QDECL SVPR_Event_ContentsTransition(world_t *w, wedict_t *ent, i #define H2MP_PROGHEADER_CRC 26905 //hexen2 mission pack uses slightly different defs... *sigh*... #define H2DEMO_PROGHEADER_CRC 14046 //I'm guessing this is from the original release or something -pbool PDECL PR_SSQC_CheckHeaderCrc(pubprogfuncs_t *inst, progsnum_t idx, int crc) +pbool PDECL PR_SSQC_CheckHeaderCrc(pubprogfuncs_t *inst, progsnum_t idx, int crc, const char *filename) { progstype_t modtype; if (crc == QW_PROGHEADER_CRC) @@ -734,7 +734,10 @@ pbool PDECL PR_SSQC_CheckHeaderCrc(pubprogfuncs_t *inst, progsnum_t idx, int crc progstype = modtype; //if the new one differs from the main module, reject it, unless it has crc 0, which we'll allow as a universal mutator (good luck guessing the correct arguments, but hey). if (progstype != modtype && crc != 0) + { + Con_Printf("Unable to load \"%s\" due to mismatched gametype/progdefs\n", filename); return false; + } return true; } static void *PDECL SSQC_PRReadFile (const char *path, qbyte *(PDECL *buf_get)(void *buf_ctx, size_t size), void *buf_ctx, size_t *size, pbool issource) diff --git a/engine/server/sv_cluster.c b/engine/server/sv_cluster.c index 210fbc20c..dd9f1c6c7 100644 --- a/engine/server/sv_cluster.c +++ b/engine/server/sv_cluster.c @@ -1260,10 +1260,12 @@ qboolean MSV_ClusterLoginSQLResult(queryrequest_t *req, int firstrow, int numrow } #endif -qboolean MSV_IgnoreSQLResult(queryrequest_t *req, int firstrow, int numrows, int numcols, qboolean eof) +#if 0 +static qboolean MSV_IgnoreSQLResult(queryrequest_t *req, int firstrow, int numrows, int numcols, qboolean eof) { return false; } +#endif void MSV_OpenUserDatabase(void) { #if 0 diff --git a/engine/server/sv_main.c b/engine/server/sv_main.c index 183a04586..a46805214 100644 --- a/engine/server/sv_main.c +++ b/engine/server/sv_main.c @@ -1132,7 +1132,7 @@ static void SVC_Status (void) int ping; int top, bottom; char frags[64]; - char *skin, *team, *botpre; + char *skin, *team, *botpre, *specpre; int slots=0; @@ -1170,6 +1170,7 @@ static void SVC_Status (void) else botpre = ""; + specpre = ""; if (cl->spectator) { //silly mvdsv stuff if (displayflags & STATUS_SPECTATORS_AS_PLAYERS) @@ -1181,7 +1182,7 @@ static void SVC_Status (void) { ping = -ping; sprintf(frags, "%i", -9999); - name = va("\\s\\%s", name); + specpre = "\\s\\"; } } else @@ -1189,15 +1190,15 @@ static void SVC_Status (void) if (displayflags & STATUS_SHOWTEAMS) { - Con_Printf ("%i %s %i %i \"%s%s\" \"%s\" %i %i \"%s\"\n", cl->userid, + Con_Printf ("%i %s %i %i \"%s%s%s\" \"%s\" %i %i \"%s\"\n", cl->userid, frags, (int)(realtime - cl->connection_started)/60, - ping, botpre, name, skin, top, bottom, team); + ping, specpre, botpre, name, skin, top, bottom, team); } else { - Con_Printf ("%i %s %i %i \"%s%s\" \"%s\" %i %i\n", cl->userid, + Con_Printf ("%i %s %i %i \"%s%s%s\" \"%s\" %i %i\n", cl->userid, frags, (int)(realtime - cl->connection_started)/60, - ping, botpre, name, skin, top, bottom); + ping, specpre, botpre, name, skin, top, bottom); } } else diff --git a/engine/shaders/glsl/defaultskin.glsl b/engine/shaders/glsl/defaultskin.glsl index 8a35d1931..e85288e23 100644 --- a/engine/shaders/glsl/defaultskin.glsl +++ b/engine/shaders/glsl/defaultskin.glsl @@ -13,6 +13,7 @@ !!cvardf r_tessellation_level=5 !!samps !EIGHTBIT diffuse normalmap specular fullbright upper lower reflectmask reflectcube !!samps =EIGHTBIT paletted 1 +!!samps =OCCLUDE occlusion //!!permu VC // adds rgba vertex colour multipliers //!!permu SPECULAR // auto-added when gl_specular>0 //!!permu OFFSETMAPPING // auto-added when r_glsl_offsetmapping is set @@ -21,6 +22,7 @@ //!!permu SG // specularmap is rgb:F0, a:Roughness (instead of exponent) //!!permu PBR // an attempt at pbr logic (enabled from ORM or SG) //!!permu NOOCCLUDE // ignores the use of ORM's occlusion... yeah, stupid. +//!!permu OCCLUDE // use an explicit occlusion texturemap (separate from roughness+metalness). //!!permu EIGHTBIT // uses software-style paletted colourmap lookups //!!permu ALPHATEST // if defined, this is the required alpha level (more versatile than doing it at the q3shader level) @@ -329,12 +331,12 @@ void main () #define ambientrgb (specrgb+col.rgb) vec3 specrgb = mix(vec3(dielectricSpecular), col.rgb, metalness); col.rgb = col.rgb * (1.0 - dielectricSpecular) * (1.0-metalness); - #elif defined(SG) //pbr-style specular+glossiness + #elif defined(SG) //pbr-style specular+glossiness, without occlusion //occlusion needs to be baked in. :( #define roughness (1.0-specs.a) #define gloss (specs.a) #define specrgb specs.rgb - #define ambientrgb (specs.rgb+col.rgb) + #define ambientrgb (specrgb+col.rgb) #else //blinn-phong #define roughness (1.0-specs.a) #define gloss specs.a @@ -378,7 +380,9 @@ void main () col.rgb += texture2D(s_reflectmask, tc).rgb * textureCube(s_reflectcube, rtc).rgb; #endif -#if defined(occlusion) && !defined(NOOCCLUDE) +#ifdef OCCLUDE + col.rgb *= texture2D(s_occlusion, tc).r; +#elif defined(occlusion) && !defined(NOOCCLUDE) col.rgb *= occlusion; #endif col *= light * e_colourident; diff --git a/engine/shaders/vulkan/defaultwall.glsl b/engine/shaders/vulkan/defaultwall.glsl index 34973d304..079607cee 100644 --- a/engine/shaders/vulkan/defaultwall.glsl +++ b/engine/shaders/vulkan/defaultwall.glsl @@ -8,8 +8,8 @@ !!samps diffuse normalmap specular fullbright lightmap !!samps deluxmap reflectmask reflectcube !!argb vertexlit=0 -!!samps paletted 1 -!!argb eightbit=0 +//!!samps =EIGHTBIT paletted 1 +//!!argb eightbit=0 !!argf mask=1.0 !!argb masklt=false !!permu FOG @@ -114,7 +114,7 @@ void main () lightmaps += texture2D(s_lightmap3, lm3).rgb * e_lmscale[3].rgb; } #else - if (arg_eightbit) + /*if (arg_eightbit) { //optional: round the lightmap coords to ensure all pixels within a texel have different lighting values either. it just looks wrong otherwise. //don't bother if its lightstyled, such cases will have unpredictable correlations anyway. @@ -122,7 +122,7 @@ void main () vec2 nearestlm0 = floor(lm0 * 256.0*8.0)/(256.0*8.0); lightmaps = (texture2D(s_lightmap, nearestlm0) * e_lmscale).rgb; } - else + else*/ lightmaps = (texture2D(s_lightmap, lm0) * e_lmscale).rgb; //modulate by the bumpmap dot light if (DELUXE) @@ -165,7 +165,7 @@ void main () gl_FragColor.rgb += texture2D(s_reflectmask, tc).rgb * textureCube(s_reflectcube, rtc).rgb; } - if (arg_eightbit) + /*if (arg_eightbit) { //FIXME: with this extra flag, half the permutations are redundant. lightmaps *= 0.5; //counter the fact that the colourmap contains overbright values and logically ranges from 0 to 2 intead of to 1. @@ -175,7 +175,7 @@ void main () gl_FragColor.g = texture2D(s_colourmap, vec2(pal, 1.0-lightmaps.g)).g; //its not very softwarey, but re-palettizing is ugly. gl_FragColor.b = texture2D(s_colourmap, vec2(pal, 1.0-lightmaps.b)).b; //without lits, it should be identical. } - else + else*/ { //now we have our diffuse+specular terms, modulate by lightmap values. gl_FragColor.rgb *= lightmaps.rgb; diff --git a/engine/vk/vk_init.c b/engine/vk/vk_init.c index 532dbeef8..36d9943e0 100644 --- a/engine/vk/vk_init.c +++ b/engine/vk/vk_init.c @@ -6,18 +6,45 @@ #include "renderque.h" //is anything still using this? extern qboolean vid_isfullscreen; -extern cvar_t vk_submissionthread; -extern cvar_t vk_debug; -extern cvar_t vk_dualqueue; -extern cvar_t vk_busywait; -extern cvar_t vk_waitfence; -extern cvar_t vk_nv_glsl_shader; -extern cvar_t vk_khr_get_memory_requirements2; -extern cvar_t vk_khr_dedicated_allocation; -extern cvar_t vk_khr_push_descriptor; -extern cvar_t vk_amd_rasterization_order; -extern cvar_t vk_usememorypools; + +cvar_t vk_stagingbuffers = CVARFD ("vk_stagingbuffers", "", CVAR_RENDERERLATCH, "Configures which dynamic buffers are copied into gpu memory for rendering, instead of reading from shared memory. Empty for default settings.\nAccepted chars are u(niform), e(lements), v(ertex), 0(none)."); +static cvar_t vk_submissionthread = CVARD ("vk_submissionthread", "", "Execute submits+presents on a thread dedicated to executing them. This may be a significant speedup on certain drivers."); +static cvar_t vk_debug = CVARFD("vk_debug", "0", CVAR_VIDEOLATCH, "Register a debug handler to display driver/layer messages. 2 enables the standard validation layers."); +static cvar_t vk_dualqueue = CVARFD("vk_dualqueue", "", CVAR_VIDEOLATCH, "Attempt to use a separate queue for presentation. Blank for default."); +static cvar_t vk_busywait = CVARD ("vk_busywait", "", "Force busy waiting until the GPU finishes doing its thing."); +static cvar_t vk_waitfence = CVARD ("vk_waitfence", "", "Waits on fences, instead of semaphores. This is more likely to result in gpu stalls while the cpu waits."); +static cvar_t vk_usememorypools = CVARFD("vk_usememorypools", "", CVAR_VIDEOLATCH, "Allocates memory pools for sub allocations. Vulkan has a limit to the number of memory allocations allowed so this should always be enabled, however at this time FTE is unable to reclaim pool memory, and would require periodic vid_restarts to flush them."); +static cvar_t vk_nv_glsl_shader = CVARFD("vk_loadglsl", "", CVAR_VIDEOLATCH, "Enable direct loading of glsl, where supported by drivers. Do not use in combination with vk_debug 2 (vk_debug should be 1 if you want to see any glsl compile errors). Don't forget to do a vid_restart after."); +static cvar_t vk_khr_get_memory_requirements2 = CVARFD("vk_khr_get_memory_requirements2", "", CVAR_VIDEOLATCH, "Enable extended memory info querires"); +static cvar_t vk_khr_dedicated_allocation = CVARFD("vk_khr_dedicated_allocation", "", CVAR_VIDEOLATCH, "Flag vulkan memory allocations as dedicated, where applicable."); +static cvar_t vk_khr_push_descriptor = CVARFD("vk_khr_push_descriptor", "", CVAR_VIDEOLATCH, "Enables better descriptor streaming."); +static cvar_t vk_amd_rasterization_order = CVARFD("vk_amd_rasterization_order", "", CVAR_VIDEOLATCH, "Enables the use of relaxed rasterization ordering, for a small speedup at the minor risk of a little zfighting."); +#ifdef VK_EXT_astc_decode_mode +static cvar_t vk_ext_astc_decode_mode = CVARFD("vk_ext_astc_decode_mode", "", CVAR_VIDEOLATCH, "Enables reducing texture cache sizes for LDR ASTC-compressed textures."); +#endif extern cvar_t vid_srgb, vid_vsync, vid_triplebuffer, r_stereo_method, vid_multisample, vid_bpp; + + +void VK_RegisterVulkanCvars(void) +{ +#define VKRENDEREROPTIONS "Vulkan-Specific Renderer Options" + Cvar_Register (&vk_stagingbuffers, VKRENDEREROPTIONS); + Cvar_Register (&vk_submissionthread, VKRENDEREROPTIONS); + Cvar_Register (&vk_debug, VKRENDEREROPTIONS); + Cvar_Register (&vk_dualqueue, VKRENDEREROPTIONS); + Cvar_Register (&vk_busywait, VKRENDEREROPTIONS); + Cvar_Register (&vk_waitfence, VKRENDEREROPTIONS); + Cvar_Register (&vk_usememorypools, VKRENDEREROPTIONS); + + Cvar_Register (&vk_nv_glsl_shader, VKRENDEREROPTIONS); + Cvar_Register (&vk_khr_get_memory_requirements2,VKRENDEREROPTIONS); + Cvar_Register (&vk_khr_dedicated_allocation,VKRENDEREROPTIONS); + Cvar_Register (&vk_khr_push_descriptor, VKRENDEREROPTIONS); + Cvar_Register (&vk_amd_rasterization_order, VKRENDEREROPTIONS); +#ifdef VK_EXT_astc_decode_mode + Cvar_Register (&vk_ext_astc_decode_mode, VKRENDEREROPTIONS); +#endif +} void R2D_Console_Resize(void); extern qboolean scr_con_forcedraw; @@ -1299,7 +1326,10 @@ vk_image_t VK_CreateTexture2DArray(uint32_t width, uint32_t height, uint32_t lay vk_image_t ret; VkImageViewCreateInfo viewInfo = {VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO}; VkImageCreateInfo ici = {VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO}; - VkFormat format = VK_FORMAT_UNDEFINED;; + VkFormat format = VK_FORMAT_UNDEFINED; +#ifdef VK_EXT_astc_decode_mode + VkImageViewASTCDecodeModeEXT astcmode; +#endif ret.width = width; ret.height = height; @@ -1370,34 +1400,65 @@ vk_image_t VK_CreateTexture2DArray(uint32_t width, uint32_t height, uint32_t lay case PTI_EAC_RG11: format = VK_FORMAT_EAC_R11G11_UNORM_BLOCK; break; case PTI_EAC_RG11_SNORM: format = VK_FORMAT_EAC_R11G11_SNORM_BLOCK; break; - case PTI_ASTC_4X4: format = VK_FORMAT_ASTC_4x4_UNORM_BLOCK; break; + case PTI_ASTC_4X4_LDR: format = VK_FORMAT_ASTC_4x4_UNORM_BLOCK; break; case PTI_ASTC_4X4_SRGB: format = VK_FORMAT_ASTC_4x4_SRGB_BLOCK; break; - case PTI_ASTC_5X4: format = VK_FORMAT_ASTC_5x4_UNORM_BLOCK; break; + case PTI_ASTC_5X4_LDR: format = VK_FORMAT_ASTC_5x4_UNORM_BLOCK; break; case PTI_ASTC_5X4_SRGB: format = VK_FORMAT_ASTC_5x4_SRGB_BLOCK; break; - case PTI_ASTC_5X5: format = VK_FORMAT_ASTC_5x5_UNORM_BLOCK; break; + case PTI_ASTC_5X5_LDR: format = VK_FORMAT_ASTC_5x5_UNORM_BLOCK; break; case PTI_ASTC_5X5_SRGB: format = VK_FORMAT_ASTC_5x5_SRGB_BLOCK; break; - case PTI_ASTC_6X5: format = VK_FORMAT_ASTC_6x5_UNORM_BLOCK; break; + case PTI_ASTC_6X5_LDR: format = VK_FORMAT_ASTC_6x5_UNORM_BLOCK; break; case PTI_ASTC_6X5_SRGB: format = VK_FORMAT_ASTC_6x5_SRGB_BLOCK; break; - case PTI_ASTC_6X6: format = VK_FORMAT_ASTC_6x6_UNORM_BLOCK; break; + case PTI_ASTC_6X6_LDR: format = VK_FORMAT_ASTC_6x6_UNORM_BLOCK; break; case PTI_ASTC_6X6_SRGB: format = VK_FORMAT_ASTC_6x6_SRGB_BLOCK; break; - case PTI_ASTC_8X5: format = VK_FORMAT_ASTC_8x5_UNORM_BLOCK; break; + case PTI_ASTC_8X5_LDR: format = VK_FORMAT_ASTC_8x5_UNORM_BLOCK; break; case PTI_ASTC_8X5_SRGB: format = VK_FORMAT_ASTC_8x5_SRGB_BLOCK; break; - case PTI_ASTC_8X6: format = VK_FORMAT_ASTC_8x6_UNORM_BLOCK; break; + case PTI_ASTC_8X6_LDR: format = VK_FORMAT_ASTC_8x6_UNORM_BLOCK; break; case PTI_ASTC_8X6_SRGB: format = VK_FORMAT_ASTC_8x6_SRGB_BLOCK; break; - case PTI_ASTC_8X8: format = VK_FORMAT_ASTC_8x8_UNORM_BLOCK; break; + case PTI_ASTC_8X8_LDR: format = VK_FORMAT_ASTC_8x8_UNORM_BLOCK; break; case PTI_ASTC_8X8_SRGB: format = VK_FORMAT_ASTC_8x8_SRGB_BLOCK; break; - case PTI_ASTC_10X5: format = VK_FORMAT_ASTC_10x5_UNORM_BLOCK; break; + case PTI_ASTC_10X5_LDR: format = VK_FORMAT_ASTC_10x5_UNORM_BLOCK; break; case PTI_ASTC_10X5_SRGB: format = VK_FORMAT_ASTC_10x5_SRGB_BLOCK; break; - case PTI_ASTC_10X6: format = VK_FORMAT_ASTC_10x6_UNORM_BLOCK; break; + case PTI_ASTC_10X6_LDR: format = VK_FORMAT_ASTC_10x6_UNORM_BLOCK; break; case PTI_ASTC_10X6_SRGB: format = VK_FORMAT_ASTC_10x6_SRGB_BLOCK; break; - case PTI_ASTC_10X8: format = VK_FORMAT_ASTC_10x8_UNORM_BLOCK; break; + case PTI_ASTC_10X8_LDR: format = VK_FORMAT_ASTC_10x8_UNORM_BLOCK; break; case PTI_ASTC_10X8_SRGB: format = VK_FORMAT_ASTC_10x8_SRGB_BLOCK; break; - case PTI_ASTC_10X10: format = VK_FORMAT_ASTC_10x10_UNORM_BLOCK; break; + case PTI_ASTC_10X10_LDR: format = VK_FORMAT_ASTC_10x10_UNORM_BLOCK; break; case PTI_ASTC_10X10_SRGB: format = VK_FORMAT_ASTC_10x10_SRGB_BLOCK; break; - case PTI_ASTC_12X10: format = VK_FORMAT_ASTC_12x10_UNORM_BLOCK; break; + case PTI_ASTC_12X10_LDR: format = VK_FORMAT_ASTC_12x10_UNORM_BLOCK; break; case PTI_ASTC_12X10_SRGB: format = VK_FORMAT_ASTC_12x10_SRGB_BLOCK; break; - case PTI_ASTC_12X12: format = VK_FORMAT_ASTC_12x12_UNORM_BLOCK; break; + case PTI_ASTC_12X12_LDR: format = VK_FORMAT_ASTC_12x12_UNORM_BLOCK; break; case PTI_ASTC_12X12_SRGB: format = VK_FORMAT_ASTC_12x12_SRGB_BLOCK; break; +#ifdef VK_EXT_texture_compression_astc_hdr + case PTI_ASTC_4X4_HDR: format = VK_FORMAT_ASTC_4x4_SFLOAT_BLOCK_EXT; break; + case PTI_ASTC_5X4_HDR: format = VK_FORMAT_ASTC_5x4_SFLOAT_BLOCK_EXT; break; + case PTI_ASTC_5X5_HDR: format = VK_FORMAT_ASTC_5x5_SFLOAT_BLOCK_EXT; break; + case PTI_ASTC_6X5_HDR: format = VK_FORMAT_ASTC_6x5_SFLOAT_BLOCK_EXT; break; + case PTI_ASTC_6X6_HDR: format = VK_FORMAT_ASTC_6x6_SFLOAT_BLOCK_EXT; break; + case PTI_ASTC_8X5_HDR: format = VK_FORMAT_ASTC_8x5_SFLOAT_BLOCK_EXT; break; + case PTI_ASTC_8X6_HDR: format = VK_FORMAT_ASTC_8x6_SFLOAT_BLOCK_EXT; break; + case PTI_ASTC_8X8_HDR: format = VK_FORMAT_ASTC_8x8_SFLOAT_BLOCK_EXT; break; + case PTI_ASTC_10X5_HDR: format = VK_FORMAT_ASTC_10x5_SFLOAT_BLOCK_EXT; break; + case PTI_ASTC_10X6_HDR: format = VK_FORMAT_ASTC_10x6_SFLOAT_BLOCK_EXT; break; + case PTI_ASTC_10X8_HDR: format = VK_FORMAT_ASTC_10x8_SFLOAT_BLOCK_EXT; break; + case PTI_ASTC_10X10_HDR: format = VK_FORMAT_ASTC_10x10_SFLOAT_BLOCK_EXT; break; + case PTI_ASTC_12X10_HDR: format = VK_FORMAT_ASTC_12x10_SFLOAT_BLOCK_EXT; break; + case PTI_ASTC_12X12_HDR: format = VK_FORMAT_ASTC_12x12_SFLOAT_BLOCK_EXT; break; +#else //better than crashing. + case PTI_ASTC_4X4_HDR: format = VK_FORMAT_ASTC_4x4_UNORM_BLOCK; break; + case PTI_ASTC_5X4_HDR: format = VK_FORMAT_ASTC_5x4_UNORM_BLOCK; break; + case PTI_ASTC_5X5_HDR: format = VK_FORMAT_ASTC_5x5_UNORM_BLOCK; break; + case PTI_ASTC_6X5_HDR: format = VK_FORMAT_ASTC_6x5_UNORM_BLOCK; break; + case PTI_ASTC_6X6_HDR: format = VK_FORMAT_ASTC_6x6_UNORM_BLOCK; break; + case PTI_ASTC_8X5_HDR: format = VK_FORMAT_ASTC_8x5_UNORM_BLOCK; break; + case PTI_ASTC_8X6_HDR: format = VK_FORMAT_ASTC_8x6_UNORM_BLOCK; break; + case PTI_ASTC_8X8_HDR: format = VK_FORMAT_ASTC_8x8_UNORM_BLOCK; break; + case PTI_ASTC_10X5_HDR: format = VK_FORMAT_ASTC_10x5_UNORM_BLOCK; break; + case PTI_ASTC_10X6_HDR: format = VK_FORMAT_ASTC_10x6_UNORM_BLOCK; break; + case PTI_ASTC_10X8_HDR: format = VK_FORMAT_ASTC_10x8_UNORM_BLOCK; break; + case PTI_ASTC_10X10_HDR: format = VK_FORMAT_ASTC_10x10_UNORM_BLOCK; break; + case PTI_ASTC_12X10_HDR: format = VK_FORMAT_ASTC_12x10_UNORM_BLOCK; break; + case PTI_ASTC_12X12_HDR: format = VK_FORMAT_ASTC_12x12_UNORM_BLOCK; break; +#endif //depth formats case PTI_DEPTH16: format = VK_FORMAT_D16_UNORM; break; @@ -1473,7 +1534,8 @@ vk_image_t VK_CreateTexture2DArray(uint32_t width, uint32_t height, uint32_t lay viewInfo.components.b = VK_COMPONENT_SWIZZLE_B; viewInfo.components.a = VK_COMPONENT_SWIZZLE_ONE; break; - case PTI_L8: //must be an R8 texture + case PTI_L8: //must be an R8 texture + case PTI_L8_SRGB: //must be an R8 texture viewInfo.components.r = VK_COMPONENT_SWIZZLE_R; viewInfo.components.g = VK_COMPONENT_SWIZZLE_R; viewInfo.components.b = VK_COMPONENT_SWIZZLE_R; @@ -1491,6 +1553,35 @@ vk_image_t VK_CreateTexture2DArray(uint32_t width, uint32_t height, uint32_t lay viewInfo.components.b = VK_COMPONENT_SWIZZLE_IDENTITY; viewInfo.components.a = VK_COMPONENT_SWIZZLE_IDENTITY; break; + +#ifdef VK_EXT_astc_decode_mode + case PTI_ASTC_4X4: //set these to use rgba8 decoding, because we know they're not hdr and the format is basically 8bit anyway. + case PTI_ASTC_5X4: //we do NOT do this for the hdr, as that would cause data loss. + case PTI_ASTC_5X5: //we do NOT do this for sRGB because its pointless. + case PTI_ASTC_6X5: + case PTI_ASTC_6X6: + case PTI_ASTC_8X5: + case PTI_ASTC_8X6: + case PTI_ASTC_8X8: + case PTI_ASTC_10X5: + case PTI_ASTC_10X6: + case PTI_ASTC_10X8: + case PTI_ASTC_10X10: + case PTI_ASTC_12X10: + case PTI_ASTC_12X12: + viewInfo.components.r = VK_COMPONENT_SWIZZLE_IDENTITY; + viewInfo.components.g = VK_COMPONENT_SWIZZLE_IDENTITY; + viewInfo.components.b = VK_COMPONENT_SWIZZLE_IDENTITY; + viewInfo.components.a = VK_COMPONENT_SWIZZLE_IDENTITY; + if (vk.ext_astc_decode_mode) + { + astcmode.pNext = viewInfo.pNext; + astcmode.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_ASTC_DECODE_MODE_EXT; + astcmode.decodeMode = VK_FORMAT_R8G8B8A8_UNORM; + viewInfo.pNext = &astcmode; + } + break; +#endif } viewInfo.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; viewInfo.subresourceRange.baseMipLevel = 0; @@ -3994,7 +4085,9 @@ void VK_CheckTextureFormats(void) {PTI_ARGB1555, VK_FORMAT_A1R5G5B5_UNORM_PACK16, VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT}, {PTI_RGBA16F, VK_FORMAT_R16G16B16A16_SFLOAT, VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT|VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT|VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT}, {PTI_RGBA32F, VK_FORMAT_R32G32B32A32_SFLOAT, VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT|VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT|VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT}, - {PTI_P8, VK_FORMAT_R8_UNORM, VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT}, + {PTI_L8, VK_FORMAT_R8_UNORM, VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT}, + {PTI_L8A8, VK_FORMAT_R8G8_UNORM, VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT}, + {PTI_L8_SRGB, VK_FORMAT_R8_SRGB, VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT}, {PTI_R8, VK_FORMAT_R8_UNORM, VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT}, {PTI_RG8, VK_FORMAT_R8G8_UNORM, VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT}, {PTI_R8_SNORM, VK_FORMAT_R8_SNORM, VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT}, @@ -4036,34 +4129,51 @@ void VK_CheckTextureFormats(void) {PTI_EAC_R11_SNORM, VK_FORMAT_EAC_R11_SNORM_BLOCK, VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT}, {PTI_EAC_RG11, VK_FORMAT_EAC_R11G11_UNORM_BLOCK, VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT}, {PTI_EAC_RG11_SNORM, VK_FORMAT_EAC_R11G11_SNORM_BLOCK, VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT}, - {PTI_ASTC_4X4, VK_FORMAT_ASTC_4x4_UNORM_BLOCK, VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT}, + {PTI_ASTC_4X4_LDR, VK_FORMAT_ASTC_4x4_UNORM_BLOCK, VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT}, + {PTI_ASTC_5X4_LDR, VK_FORMAT_ASTC_5x4_UNORM_BLOCK, VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT}, + {PTI_ASTC_5X5_LDR, VK_FORMAT_ASTC_5x5_UNORM_BLOCK, VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT}, + {PTI_ASTC_6X5_LDR, VK_FORMAT_ASTC_6x5_UNORM_BLOCK, VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT}, + {PTI_ASTC_6X6_LDR, VK_FORMAT_ASTC_6x6_UNORM_BLOCK, VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT}, + {PTI_ASTC_8X5_LDR, VK_FORMAT_ASTC_8x5_UNORM_BLOCK, VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT}, + {PTI_ASTC_8X6_LDR, VK_FORMAT_ASTC_8x6_UNORM_BLOCK, VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT}, + {PTI_ASTC_8X8_LDR, VK_FORMAT_ASTC_8x8_UNORM_BLOCK, VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT}, + {PTI_ASTC_10X5_LDR, VK_FORMAT_ASTC_10x5_UNORM_BLOCK, VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT}, + {PTI_ASTC_10X6_LDR, VK_FORMAT_ASTC_10x6_UNORM_BLOCK, VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT}, + {PTI_ASTC_10X8_LDR, VK_FORMAT_ASTC_10x8_UNORM_BLOCK, VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT}, + {PTI_ASTC_10X10_LDR, VK_FORMAT_ASTC_10x10_UNORM_BLOCK, VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT}, + {PTI_ASTC_12X10_LDR, VK_FORMAT_ASTC_12x10_UNORM_BLOCK, VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT}, + {PTI_ASTC_12X12_LDR, VK_FORMAT_ASTC_12x12_UNORM_BLOCK, VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT}, {PTI_ASTC_4X4_SRGB, VK_FORMAT_ASTC_4x4_SRGB_BLOCK, VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT}, - {PTI_ASTC_5X4, VK_FORMAT_ASTC_5x4_UNORM_BLOCK, VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT}, {PTI_ASTC_5X4_SRGB, VK_FORMAT_ASTC_5x4_SRGB_BLOCK, VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT}, - {PTI_ASTC_5X5, VK_FORMAT_ASTC_5x5_UNORM_BLOCK, VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT}, {PTI_ASTC_5X5_SRGB, VK_FORMAT_ASTC_5x5_SRGB_BLOCK, VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT}, - {PTI_ASTC_6X5, VK_FORMAT_ASTC_6x5_UNORM_BLOCK, VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT}, {PTI_ASTC_6X5_SRGB, VK_FORMAT_ASTC_6x5_SRGB_BLOCK, VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT}, - {PTI_ASTC_6X6, VK_FORMAT_ASTC_6x6_UNORM_BLOCK, VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT}, {PTI_ASTC_6X6_SRGB, VK_FORMAT_ASTC_6x6_SRGB_BLOCK, VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT}, - {PTI_ASTC_8X5, VK_FORMAT_ASTC_8x5_UNORM_BLOCK, VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT}, {PTI_ASTC_8X5_SRGB, VK_FORMAT_ASTC_8x5_SRGB_BLOCK, VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT}, - {PTI_ASTC_8X6, VK_FORMAT_ASTC_8x6_UNORM_BLOCK, VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT}, {PTI_ASTC_8X6_SRGB, VK_FORMAT_ASTC_8x6_SRGB_BLOCK, VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT}, - {PTI_ASTC_8X8, VK_FORMAT_ASTC_8x8_UNORM_BLOCK, VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT}, {PTI_ASTC_8X8_SRGB, VK_FORMAT_ASTC_8x8_SRGB_BLOCK, VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT}, - {PTI_ASTC_10X5, VK_FORMAT_ASTC_10x5_UNORM_BLOCK, VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT}, {PTI_ASTC_10X5_SRGB, VK_FORMAT_ASTC_10x5_SRGB_BLOCK, VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT}, - {PTI_ASTC_10X6, VK_FORMAT_ASTC_10x6_UNORM_BLOCK, VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT}, {PTI_ASTC_10X6_SRGB, VK_FORMAT_ASTC_10x6_SRGB_BLOCK, VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT}, - {PTI_ASTC_10X8, VK_FORMAT_ASTC_10x8_UNORM_BLOCK, VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT}, {PTI_ASTC_10X8_SRGB, VK_FORMAT_ASTC_10x8_SRGB_BLOCK, VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT}, - {PTI_ASTC_10X10, VK_FORMAT_ASTC_10x10_UNORM_BLOCK, VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT}, {PTI_ASTC_10X10_SRGB, VK_FORMAT_ASTC_10x10_SRGB_BLOCK, VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT}, - {PTI_ASTC_12X10, VK_FORMAT_ASTC_12x10_UNORM_BLOCK, VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT}, {PTI_ASTC_12X10_SRGB, VK_FORMAT_ASTC_12x10_SRGB_BLOCK, VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT}, - {PTI_ASTC_12X12, VK_FORMAT_ASTC_12x12_UNORM_BLOCK, VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT}, {PTI_ASTC_12X12_SRGB, VK_FORMAT_ASTC_12x12_SRGB_BLOCK, VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT}, + +#ifdef VK_EXT_texture_compression_astc_hdr + {PTI_ASTC_4X4_HDR, VK_FORMAT_ASTC_4x4_SFLOAT_BLOCK_EXT, VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT}, + {PTI_ASTC_5X4_HDR, VK_FORMAT_ASTC_5x4_SFLOAT_BLOCK_EXT, VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT}, + {PTI_ASTC_5X5_HDR, VK_FORMAT_ASTC_5x5_SFLOAT_BLOCK_EXT, VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT}, + {PTI_ASTC_6X5_HDR, VK_FORMAT_ASTC_6x5_SFLOAT_BLOCK_EXT, VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT}, + {PTI_ASTC_6X6_HDR, VK_FORMAT_ASTC_6x6_SFLOAT_BLOCK_EXT, VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT}, + {PTI_ASTC_8X5_HDR, VK_FORMAT_ASTC_8x5_SFLOAT_BLOCK_EXT, VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT}, + {PTI_ASTC_8X6_HDR, VK_FORMAT_ASTC_8x6_SFLOAT_BLOCK_EXT, VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT}, + {PTI_ASTC_8X8_HDR, VK_FORMAT_ASTC_8x8_SFLOAT_BLOCK_EXT, VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT}, + {PTI_ASTC_10X5_HDR, VK_FORMAT_ASTC_10x5_SFLOAT_BLOCK_EXT, VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT}, + {PTI_ASTC_10X6_HDR, VK_FORMAT_ASTC_10x6_SFLOAT_BLOCK_EXT, VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT}, + {PTI_ASTC_10X8_HDR, VK_FORMAT_ASTC_10x8_SFLOAT_BLOCK_EXT, VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT}, + {PTI_ASTC_10X10_HDR, VK_FORMAT_ASTC_10x10_SFLOAT_BLOCK_EXT, VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT}, + {PTI_ASTC_12X10_HDR, VK_FORMAT_ASTC_12x10_SFLOAT_BLOCK_EXT, VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT}, + {PTI_ASTC_12X12_HDR, VK_FORMAT_ASTC_12x12_SFLOAT_BLOCK_EXT, VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT}, +#endif }; unsigned int i; VkPhysicalDeviceProperties props; @@ -4083,6 +4193,15 @@ void VK_CheckTextureFormats(void) if ((fmt.optimalTilingFeatures & need) == need) sh_config.texfmt[texfmt[i].pti] = true; } + + if (sh_config.texfmt[PTI_BC1_RGBA] && sh_config.texfmt[PTI_BC2_RGBA] && sh_config.texfmt[PTI_BC3_RGBA] && sh_config.texfmt[PTI_BC5_RG8] && sh_config.texfmt[PTI_BC7_RGBA]) + sh_config.hw_bc = 3; + if (sh_config.texfmt[PTI_ETC2_RGB8] && sh_config.texfmt[PTI_ETC2_RGB8A1] && sh_config.texfmt[PTI_ETC2_RGB8A8] && sh_config.texfmt[PTI_EAC_RG11]) + sh_config.hw_etc = 2; + if (sh_config.texfmt[PTI_ASTC_4X4_LDR]) + sh_config.hw_astc = 1; //the core vulkan formats refer to the ldr profile. hdr is a separate extension, which is still not properly specified.. + if (sh_config.texfmt[PTI_ASTC_4X4_HDR]) + sh_config.hw_astc = 2; //the core vulkan formats refer to the ldr profile. hdr is a separate extension, which is still not properly specified.. } //initialise the vulkan instance, context, device, etc. @@ -4115,6 +4234,9 @@ qboolean VK_Init(rendererstate_t *info, const char **sysextnames, qboolean (*cre {&vk.khr_dedicated_allocation, VK_KHR_DEDICATED_ALLOCATION_EXTENSION_NAME, &vk_khr_dedicated_allocation, true, NULL, NULL}, {&vk.khr_push_descriptor, VK_KHR_PUSH_DESCRIPTOR_EXTENSION_NAME, &vk_khr_push_descriptor, true, NULL, NULL}, {&vk.amd_rasterization_order, VK_AMD_RASTERIZATION_ORDER_EXTENSION_NAME, &vk_amd_rasterization_order, false, NULL, NULL}, +#ifdef VK_EXT_astc_decode_mode + {&vk.ext_astc_decode_mode, VK_EXT_ASTC_DECODE_MODE_EXTENSION_NAME, &vk_ext_astc_decode_mode, true, NULL, NULL}, +#endif }; size_t e; diff --git a/engine/vk/vkrenderer.h b/engine/vk/vkrenderer.h index ccb88b0bf..137354f58 100644 --- a/engine/vk/vkrenderer.h +++ b/engine/vk/vkrenderer.h @@ -280,6 +280,7 @@ extern struct vulkaninfo_s qboolean khr_dedicated_allocation; //standardised version of the above where the driver decides whether a resource is worth a dedicated allocation. qboolean khr_push_descriptor; //more efficient descriptor streaming qboolean amd_rasterization_order; //allows primitives to draw in any order + qboolean ext_astc_decode_mode; //small perf boost VkInstance instance; VkDevice device; diff --git a/plugins/models/exportiqm.c b/plugins/models/exportiqm.c new file mode 100644 index 000000000..cbdebcc2d --- /dev/null +++ b/plugins/models/exportiqm.c @@ -0,0 +1,660 @@ +#ifndef GLQUAKE +#define GLQUAKE //this is shit. +#endif +#include "quakedef.h" +#include "../plugin.h" +#include "com_mesh.h" +extern plugmodfuncs_t *modfuncs; +extern plugfsfuncs_t *filefuncs; + +#define IQM_MAGIC "INTERQUAKEMODEL" +#define IQM_VERSION2 2 + +struct iqmheader +{ + char magic[16]; + unsigned int version; + unsigned int filesize; + unsigned int flags; + unsigned int num_text, ofs_text; + unsigned int num_meshes, ofs_meshes; + unsigned int num_vertexarrays, num_vertexes, ofs_vertexarrays; + unsigned int num_triangles, ofs_triangles, ofs_adjacency; + unsigned int num_joints, ofs_joints; + unsigned int num_poses, ofs_poses; + unsigned int num_anims, ofs_anims; + unsigned int num_frames, num_framechannels, ofs_frames, ofs_bounds; + unsigned int num_comment, ofs_comment; + unsigned int num_extensions, ofs_extensions; +}; +struct iqmmesh +{ + unsigned int name; + unsigned int material; + unsigned int first_vertex, num_vertexes; + unsigned int first_triangle, num_triangles; +}; + +enum +{ + IQM_POSITION = 0, + IQM_TEXCOORD = 1, + IQM_NORMAL = 2, + IQM_TANGENT = 3, + IQM_BLENDINDEXES = 4, + IQM_BLENDWEIGHTS = 5, + IQM_COLOR = 6, + IQM_CUSTOM = 0x10 +}; + +enum +{ + IQM_BYTE = 0, + IQM_UBYTE = 1, + IQM_SHORT = 2, + IQM_USHORT = 3, + IQM_INT = 4, + IQM_UINT = 5, + IQM_HALF = 6, + IQM_FLOAT = 7, + IQM_DOUBLE = 8, +}; + +struct iqmtriangle +{ + unsigned int vertex[3]; +}; + +struct iqmjoint2 +{ + unsigned int name; + int parent; + float translate[3], rotate[4], scale[3]; +}; + +struct iqmpose2 +{ + int parent; + unsigned int mask; + float channeloffset[10]; + float channelscale[10]; +}; + +struct iqmanim +{ + unsigned int name; + unsigned int first_frame, num_frames; + float framerate; + unsigned int flags; +}; + +enum +{ + IQM_LOOP = 1<<0 +}; + +struct iqmvertexarray +{ + unsigned int type; + unsigned int flags; + unsigned int format; + unsigned int size; + unsigned int offset; +}; + +struct iqmbounds +{ + float bbmin[3], bbmax[3]; + float xyradius, radius; +}; + +struct iqmextension +{ + unsigned int name; + unsigned int num_data, ofs_data; + unsigned int ofs_extensions; // pointer to next extension. wtf is up with this? how is this not redundant due to ofs_data? +}; + + +struct iqmext_fte_mesh +{ + unsigned int contents; //default CONTENTS_BODY + unsigned int surfaceflags; //propagates to trace_surfaceflags + unsigned int surfaceid; //the body reported to qc via trace_surface + unsigned int geomset; + unsigned int geomid; + float mindist; + float maxdist; +}; +struct iqmext_fte_event +{ + unsigned int anim; + float timestamp; + unsigned int evcode; + unsigned int evdata_str; //stringtable +}; +static void CrossProduct_ (const vec3_t v1, const vec3_t v2, vec3_t cross) +{ + cross[0] = v1[1]*v2[2] - v1[2]*v2[1]; + cross[1] = v1[2]*v2[0] - v1[0]*v2[2]; + cross[2] = v1[0]*v2[1] - v1[1]*v2[0]; +} +static void Bone_To_PosQuat4(const float *matrix, float *pos, float *quat4, float *scale) +{ //I originally ripped this function out of DP. tweaked slightly. + //http://www.euclideanspace.com/maths/geometry/rotations/conversions/matrixToQuaternion/index.htm + float origininvscale = 1; + float origin[3]; + float quat[4]; + float quatscale; + + float trace = matrix[0*4+0] + matrix[1*4+1] + matrix[2*4+2]; + + origin[0] = matrix[0*4+0]; + origin[1] = matrix[1*4+0]; + origin[2] = matrix[2*4+0]; + scale [0] = sqrt(DotProduct(origin,origin)); + origin[0] = matrix[0*4+1]; + origin[1] = matrix[1*4+1]; + origin[2] = matrix[2*4+1]; + scale [1] = sqrt(DotProduct(origin,origin)); + origin[1] = matrix[0*4+2]; + origin[1] = matrix[1*4+2]; + origin[2] = matrix[2*4+2]; + scale [2] = sqrt(DotProduct(origin,origin)); + + origin[0] = matrix[0*4+3]; + origin[1] = matrix[1*4+3]; + origin[2] = matrix[2*4+3]; + if(trace > 0) + { + float r = sqrt(1.0f + trace), inv = 0.5f / r; + quat[0] = (matrix[2*4+1] - matrix[1*4+2]) * inv; + quat[1] = (matrix[0*4+2] - matrix[2*4+0]) * inv; + quat[2] = (matrix[1*4+0] - matrix[0*4+1]) * inv; + quat[3] = 0.5f * r; + } + else if(matrix[0*4+0] > matrix[1*4+1] && matrix[0*4+0] > matrix[2*4+2]) + { + float r = sqrt(1.0f + matrix[0*4+0] - matrix[1*4+1] - matrix[2*4+2]), inv = 0.5f / r; + quat[0] = 0.5f * r; + quat[1] = (matrix[1*4+0] + matrix[0*4+1]) * inv; + quat[2] = (matrix[0*4+2] + matrix[2*4+0]) * inv; + quat[3] = (matrix[2*4+1] - matrix[1*4+2]) * inv; + } + else if(matrix[1*4+1] > matrix[2*4+2]) + { + float r = sqrt(1.0f + matrix[1*4+1] - matrix[0*4+0] - matrix[2*4+2]), inv = 0.5f / r; + quat[0] = (matrix[1*4+0] + matrix[0*4+1]) * inv; + quat[1] = 0.5f * r; + quat[2] = (matrix[2*4+1] + matrix[1*4+2]) * inv; + quat[3] = (matrix[0*4+2] - matrix[2*4+0]) * inv; + } + else + { + float r = sqrt(1.0f + matrix[2*4+2] - matrix[0*4+0] - matrix[1*4+1]), inv = 0.5f / r; + quat[0] = (matrix[0*4+2] + matrix[2*4+0]) * inv; + quat[1] = (matrix[2*4+1] + matrix[1*4+2]) * inv; + quat[2] = 0.5f * r; + quat[3] = (matrix[1*4+0] - matrix[0*4+1]) * inv; + } + // normalize quaternion so that it is unit length + quatscale = quat[0]*quat[0]+quat[1]*quat[1]+quat[2]*quat[2]+quat[3]*quat[3]; + if (quatscale) + quatscale = (quat[3] >= 0 ? -1.0f : 1.0f) / sqrt(quatscale); + + // use a negative scale on the quat because the above function produces a + // positive quat[3] and canonical quaternions have negative quat[3] + VectorScale(origin, origininvscale, pos); + Vector4Scale(quat, quatscale, quat4); +} +void Mod_ExportIQM(char *fname, int flags, galiasinfo_t *mesh) +{ + int i, j, k; + vfsfile_t *f; + galiasinfo_t *m; + qbyte *data = NULL; + char *otext; + struct iqmvertexarray *ovarr; + struct iqmtriangle *otri; + struct iqmmesh *omesh; + struct iqmjoint2 *ojoint; + struct iqmanim *oanim; + struct iqmpose2 *opose; + struct + { + float min[10], max[10], scale[10]; + int flags; + } *poseinfo = NULL, *pi; //per bone + struct + { //pos3, quat4, scale3 + float posquatscale[10]; //raw values, used to calibrate ranges + } *posedata = NULL, *pd; //per bone*joint + avec4_t *ivert; + vec2_t *ist; + vec3_t *overt; + vec3_t *onorm = NULL; + vec4_t *otang = NULL; + vec2_t *ost; + bone_vec4_t *oboneidx; + byte_vec4_t *oboneweight; + unsigned short *oposedata; + struct iqmheader hdr = {IQM_MAGIC, IQM_VERSION2}, *oh; + hdr.flags = flags; + hdr.num_vertexarrays = 4; + hdr.num_triangles = 0; + hdr.ofs_adjacency = 0; //noone actually uses this... + hdr.num_poses = 0; +// hdr.ofs_poses = 0; + hdr.num_anims = 0; +// hdr.ofs_anims = 0; + hdr.num_frames = 0; + hdr.num_framechannels = 0; +// hdr.ofs_frames = 0; +// hdr.ofs_bounds = 0; + hdr.num_comment = 0; +// hdr.ofs_comment = 0; + hdr.num_extensions = 0; +// hdr.ofs_extensions = 0; + + + hdr.num_joints = mesh->numbones; + if (hdr.num_joints) + { + float *matrix; + hdr.num_vertexarrays+= 2; + hdr.num_anims = mesh->numanimations; + for (i = 0; i < hdr.num_anims; i++) + { + hdr.num_text += strlen(mesh->ofsanimations[i].name)+1; + hdr.num_frames += mesh->ofsanimations[i].numposes; + } + if (hdr.num_frames) + { + poseinfo = malloc(sizeof(*poseinfo)*hdr.num_joints); + hdr.num_poses = hdr.num_joints; + posedata = malloc(sizeof(*posedata)*hdr.num_joints*hdr.num_poses); + //pull out the raw data and convert to the quats that we need + for (i = 0, pd = posedata; i < hdr.num_anims; i++) + for (j = 0, matrix = mesh->ofsanimations[i].boneofs; j < mesh->ofsanimations[i].numposes; j++) + for (k = 0; k < hdr.num_joints; k++) + { + Bone_To_PosQuat4(matrix, &pd->posquatscale[0], &pd->posquatscale[3], &pd->posquatscale[7]); + pd++; + matrix+=12; + } + //now figure out each poseinfo's min+max + for (i = 0, pi = poseinfo; i < hdr.num_joints; i++, pi++) + for (j = 0, pd = posedata+i; j < hdr.num_poses; j++, pd+=hdr.num_joints) + for (k = 0; k < 10; k++) + { + if (!i || pd->posquatscale[k] < pi->min[k]) + pi->min[k] = pd->posquatscale[k]; + if (!i || pi[i].max[k] < pd->posquatscale[k]) + pi->max[k] = pd->posquatscale[k]; + } + //figure out the offset+range+flags + for (i = 0, pi = poseinfo; i < hdr.num_joints; i++, pi++) + for (k = 0; k < 10; k++) + { + pi->scale[k] = pi->max[k]-pi->min[k]; + if (pi->scale[k] < 1e-10f) + ; //total range is tiny and won't make any real difference, drop this channel for a small saving. + else + { + pi->scale[k] /= 0xffffu; //compensate for the datatype's max + pi->flags |= 1u<nextsurf) + { + //can't handle the surface if its verts are weird. + if (m->shares_verts && m->shares_verts != hdr.num_meshes) + continue; + //can only handle one set of bones. + if (m->shares_bones != 0) + continue; + //and must have the same number of bones. + if (hdr.num_joints != m->numbones) + continue; + + hdr.num_text += strlen(m->surfacename)+1; + if (m->ofsskins && m->ofsskins->frame) + hdr.num_text += strlen(m->ofsskins->frame->shadername)+1; + hdr.num_triangles += m->numindexes/3; + hdr.num_vertexes += m->numverts; + hdr.num_meshes++; + } + + //allocate our output buffer +#define ALLOCSPACE hdr.filesize = 0; \ + ALLOC(oh, sizeof(*oh)); \ + ALLOC(otext, sizeof(*otext)*hdr.num_text); \ + ALLOC(ovarr, sizeof(*ovarr)*hdr.num_vertexarrays); \ + ALLOC(otri, sizeof(*otri)*hdr.num_triangles); \ + ALLOC(overt, sizeof(*overt)*hdr.num_vertexes); \ + ALLOC(ost, sizeof(*ost)*hdr.num_vertexes); \ + if (mesh->ofs_skel_norm) {ALLOC(onorm, sizeof(*onorm)*hdr.num_vertexes);} \ + if (mesh->ofs_skel_svect && mesh->ofs_skel_tvect) {ALLOC(otang, sizeof(*otang)*hdr.num_vertexes);} \ + if (hdr.num_joints) {ALLOC(oboneweight, sizeof(*oboneweight)*hdr.num_vertexes);} \ + if (hdr.num_joints) {ALLOC(oboneidx, sizeof(*oboneidx)*hdr.num_vertexes);} \ + if (hdr.num_joints) {ALLOC(ojoint, sizeof(*ojoint)*hdr.num_joints);} \ + if (hdr.num_anims) {ALLOC(oanim, sizeof(*oanim)*hdr.num_anims);} \ + if (hdr.num_poses) {ALLOC(opose, sizeof(*opose)*hdr.num_poses);} \ + if (hdr.num_framechannels) {ALLOC(oposedata, sizeof(*oposedata)*hdr.num_framechannels);} \ + ALLOC(omesh, sizeof(*omesh)*hdr.num_meshes); +#define ALLOC(p,s) p=(void*)(data+hdr.filesize);hdr.filesize+=s; + ALLOCSPACE; //figure out how much space we need + data = malloc(hdr.filesize); + memset(data, 0xFE, hdr.filesize); + ALLOCSPACE; //and assign everything to the right offsets. +#undef ALLOC +#undef ALLOCSPACE + + //copy over the preliminary header + *oh = hdr; + +#define hdr hdr + + if (omesh) oh->ofs_meshes = (qbyte*)omesh-data; + if (otext) oh->ofs_text = (qbyte*)otext-data; + if (ovarr) oh->ofs_vertexarrays = (qbyte*)ovarr-data; + if (otri) oh->ofs_triangles = (qbyte*)otri-data; + if (ojoint) oh->ofs_joints = (qbyte*)ojoint-data; + if (opose) oh->ofs_poses = (qbyte*)opose-data; + if (oposedata) oh->ofs_frames = (qbyte*)oposedata-data; + if (oanim) oh->ofs_anims = (qbyte*)oanim-data; + + //set up vertex array data. we might add some padding here, in case the extra data isn't availble. + memset(ovarr, 0, sizeof(*ovarr)*oh->num_vertexarrays); + oh->num_vertexarrays=0; + ovarr->type = IQM_POSITION; + ovarr->flags = 0; + ovarr->format = IQM_FLOAT; + ovarr->size = 3; + ovarr->offset = (qbyte*)overt - data; + ovarr++; + oh->num_vertexarrays++; + + ovarr->type = IQM_TEXCOORD; + ovarr->flags = 0; + ovarr->format = IQM_FLOAT; + ovarr->size = 2; + ovarr->offset = (qbyte*)ost - data; + ovarr++; + oh->num_vertexarrays++; + + if (onorm) + { + ovarr->type = IQM_NORMAL; + ovarr->flags = 0; + ovarr->format = IQM_FLOAT; + ovarr->size = 3; + ovarr->offset = (qbyte*)onorm - data; + ovarr++; + oh->num_vertexarrays++; + } + if (otang) + { + ovarr->type = IQM_TANGENT; + ovarr->flags = 0; + ovarr->format = IQM_FLOAT; + ovarr->size = 4; + ovarr->offset = (qbyte*)otang - data; + ovarr++; + oh->num_vertexarrays++; + } + if (oboneidx) + { + ovarr->type = IQM_BLENDINDEXES; + ovarr->flags = 0; + ovarr->format = (MAX_BONES>65536)?IQM_UINT:((MAX_BONES>256)?IQM_USHORT:IQM_UBYTE); + ovarr->size = 4; + ovarr->offset = (qbyte*)oboneidx - data; + ovarr++; + oh->num_vertexarrays++; + } + if (oboneweight) + { + ovarr->type = IQM_BLENDWEIGHTS; + ovarr->flags = 0; + ovarr->format = IQM_BYTE; + ovarr->size = 4; + ovarr->offset = (qbyte*)oboneweight - data; + ovarr++; + oh->num_vertexarrays++; + } + /*if (orgba) + { + ovarr->type = IQM_COLOR; + ovarr->flags = 0; + ovarr->format = IQM_FLOAT; + ovarr->size = 4; + ovarr->offset = (qbyte*)orgba - data; + ovarr++; + oh->num_vertexarrays++; + }*/ + + if (ojoint) + { + for (i = 0; i < hdr.num_joints; i++) + { + ojoint[i].parent = mesh->ofsbones[i].parent; + ojoint[i].name = (qbyte*)otext-(data+oh->ofs_text); + strcpy(otext, mesh->ofsbones[i].name); + otext += strlen(otext)+1; + + Bone_To_PosQuat4(mesh->ofsbones[i].inverse, ojoint[i].translate, ojoint[i].rotate, ojoint[i].scale); + } + } + if (opose) + { + int c; + for (i = 0, pi=poseinfo; i < hdr.num_joints; i++, pi++) + { + opose[i].parent = mesh->ofsbones[i].parent; + opose[i].mask = pi->flags; + for (k = 0; k < 10; k++) + { + opose[i].channeloffset[k] = pi->min[k]; + opose[i].channelscale[k] = pi->scale[k]; + } + + for (j = 0, pd = posedata+i; j < hdr.num_frames; j++, pd+=hdr.num_joints) + { + for (k = 0; k < 10; k++) + { + if (opose[i].mask & (1<posquatscale[k]-pi->min[k])/pi->scale[k]; + c = bound(0, c, 0xffff); //clamp it just in case (floats can be annoying) + *oposedata++ = c; + } + } + } + } + } + if (oposedata) + { + for (i = 0; i < hdr.num_joints; i++) + { + opose[i].parent = mesh->ofsbones[i].parent; + opose[i].mask = poseinfo[i].flags; + for (k = 0; k < 10; k++) + { + opose[i].channeloffset[k] = poseinfo[i].min[k]; + opose[i].channelscale[k] = poseinfo[i].scale[k]; + } + } + } + + hdr.num_frames = 0; + for (i = 0; i < hdr.num_anims; i++, oanim++) + { + oanim->first_frame = hdr.num_frames; + oanim->num_frames = mesh->ofsanimations[i].numposes; + oanim->framerate = mesh->ofsanimations[i].rate; + oanim->flags = mesh->ofsanimations[i].loop?IQM_LOOP:0; + oanim->name = (qbyte*)otext-(data+oh->ofs_text); + strcpy(otext, mesh->ofsanimations[i].name); + otext += strlen(otext)+1; + hdr.num_frames += mesh->ofsanimations[i].numposes; + } + oh->num_anims = i; + oh->num_frames = hdr.num_frames; + + //count needed data + hdr.num_triangles = 0; + hdr.num_vertexes = 0; + for (m = mesh; m; m = m->nextsurf) + { + //can't handle the surface if its verts are weird. + if (m->shares_verts && m->shares_verts != hdr.num_meshes) + continue; + //can only handle one set of bones. + if (m->shares_bones != 0) + continue; + if (hdr.num_joints != m->numbones) + continue; + + omesh->name = (qbyte*)otext-(data+oh->ofs_text); + strcpy(otext, m->surfacename); + otext += strlen(otext)+1; + + omesh->material = (qbyte*)otext-(data+oh->ofs_text); + if (m->ofsskins && m->ofsskins->frame) + strcpy(otext, m->ofsskins->frame->shadername); + else + strcpy(otext, ""); + otext += strlen(otext)+1; + + omesh->first_vertex = hdr.num_vertexes; + omesh->num_vertexes = m->numverts; + omesh->first_triangle = hdr.num_triangles; + omesh->num_triangles = m->numindexes/3; + + if (m->ofs_skel_xyz) + ivert = m->ofs_skel_xyz; + else if (m->numanimations && m->ofsanimations->numposes) + ivert = m->ofsanimations->poseofs->ofsverts; + else + ivert = NULL; + if (ivert) + { + for (i = 0; i < omesh->num_vertexes; i++) + VectorCopy (ivert[i], overt[i]); + } + else + { + for (i = 0; i < omesh->num_vertexes; i++) + VectorClear (overt[i]); + + } + overt += i; + + if (oboneidx) + { + bone_vec4_t *iidx = m->ofs_skel_idx; + vec4_t *iweight = m->ofs_skel_weight; + for (i = 0; i < omesh->num_vertexes; i++) + { + Vector4Copy(iidx[i], oboneidx[i]); + Vector4Scale(iweight[i], 255, oboneweight[i]); + } + oboneidx += i; + oboneweight += i; + } + + if (ost) + { + ist = m->ofs_st_array; + for (i = 0; i < omesh->num_vertexes; i++) + Vector2Copy(ist[i], ost[i]); + ost += i; + } + + if (onorm) + { + vec3_t *inorm, *isdir, *itdir, t; + if (m->ofs_skel_norm) + { + inorm = m->ofs_skel_norm; + isdir = m->ofs_skel_svect; + itdir = m->ofs_skel_tvect; + } + else if (m->numanimations && m->ofsanimations->numposes) + { + inorm = m->ofsanimations->poseofs->ofsnormals; + isdir = m->ofsanimations->poseofs->ofssvector; + itdir = m->ofsanimations->poseofs->ofstvector; + } + else + { + inorm = NULL; + isdir = NULL; + itdir = NULL; + } + if (otang) + { + if (inorm && isdir && itdir) + { + for (i = 0; i < omesh->num_vertexes; i++) + { + VectorCopy (isdir[i], otang[i]); + CrossProduct_(isdir[i], inorm[i], t); + otang[i][3] = DotProduct(itdir[i], t)<0; //fourth part is simply a flag that says which direction the bitangent is in, should otherwise be a nice crossproduct result. + } + } + else + { + for (i = 0; i < omesh->num_vertexes; i++) + { + VectorClear (otang[i]); + otang[i][3] = 0; + } + } + otang += i; + } + if (inorm) + { + for (i = 0; i < omesh->num_vertexes; i++) + VectorCopy (ivert[i], onorm[i]); + } + else + { + for (i = 0; i < omesh->num_vertexes; i++) + VectorClear (onorm[i]); + } + otang += i; + onorm += i; + } + + for (i = 0; i < omesh->num_triangles; i++) + { + otri[i].vertex[0] = m->ofs_indexes[i*3+0]+hdr.num_vertexes; + otri[i].vertex[1] = m->ofs_indexes[i*3+1]+hdr.num_vertexes; + otri[i].vertex[2] = m->ofs_indexes[i*3+2]+hdr.num_vertexes; + } + otri += i; + + hdr.num_vertexes += omesh->num_vertexes; + hdr.num_triangles += omesh->num_triangles; + } + + //and write it out + f = filefuncs->OpenVFS(fname, "wb", FS_GAMEONLY); + if (f) + { + VFS_WRITE(f, oh, oh->filesize); + VFS_CLOSE(f); + } + free(data); + free(poseinfo); +#undef hdr +}