From 41b0d993f25c3c290df9f6ff5b744bb1cbea45c6 Mon Sep 17 00:00:00 2001 From: Spoike Date: Wed, 4 Sep 2019 08:32:22 +0000 Subject: [PATCH] smoother console scrolling (at least with the mouse) support RLE+luminance+alpha tga files. support half-float tga files. recognise hdr astc images. added appropriate fallbacks for astc support. load mip-less .astc files (mostly just for debugging stuff). allow packages to warn about required engine/gpu features. catch when stdin flags get changed to blocking by external libraries, to avoid fatal stalls. basic support for .mdx files (kingpin models) sort packages loaded via wildcards, by datetime then name, to avoid random ordering from certain filesystems. git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@5531 fc73d0e0-1445-4013-8a0c-d673dee63da5 --- engine/client/cl_ignore.c | 2 +- engine/client/cl_main.c | 15 +- engine/client/console.c | 91 +- engine/client/image.c | 1297 ++++++++++++++------ engine/client/image_astc.h | 1567 ++++++++++++++++++++++++ engine/client/keys.c | 65 +- engine/client/m_download.c | 197 ++- engine/client/m_items.c | 2 +- engine/client/merged.h | 18 +- engine/client/pr_csqc.c | 5 +- engine/client/pr_menu.c | 4 +- engine/client/r_surf.c | 2 +- engine/client/render.h | 3 +- engine/client/renderer.c | 39 +- engine/client/screen.h | 106 +- engine/client/snd_alsa.c | 117 +- engine/client/snd_dma.c | 5 +- engine/client/snd_pulse.c | 2 +- engine/client/snd_sdl.c | 12 +- engine/client/sys_linux.c | 68 +- engine/common/com_mesh.c | 373 ++++++ engine/common/common.c | 4 +- engine/common/config_fteqw.h | 3 + engine/common/console.h | 7 +- engine/common/fs.c | 91 +- engine/common/net_wins.c | 2 + engine/common/sys_linux_threads.c | 27 +- engine/gl/gl_alias.c | 2 + engine/gl/gl_draw.c | 179 ++- engine/gl/gl_heightmap.c | 27 +- engine/gl/gl_shader.c | 6 +- engine/gl/gl_shadow.c | 2 +- engine/gl/gl_vidcommon.c | 8 + engine/gl/gl_warp.c | 2 +- engine/gl/glquake.h | 2 + engine/gl/glsupp.h | 8 +- engine/gl/r_bishaders.h | 1292 ++++++++++--------- engine/gl/shader.h | 17 +- engine/qclib/pr_edict.c | 2 +- engine/qclib/progslib.h | 2 +- engine/server/pr_cmds.c | 5 +- engine/server/sv_cluster.c | 4 +- engine/server/sv_main.c | 13 +- engine/shaders/glsl/defaultskin.glsl | 10 +- engine/shaders/vulkan/defaultwall.glsl | 12 +- engine/vk/vk_init.c | 206 +++- engine/vk/vkrenderer.h | 1 + plugins/models/exportiqm.c | 660 ++++++++++ 48 files changed, 5118 insertions(+), 1466 deletions(-) create mode 100644 engine/client/image_astc.h create mode 100644 plugins/models/exportiqm.c diff --git a/engine/client/cl_ignore.c b/engine/client/cl_ignore.c index d87548fc..a39b6fb2 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 e50b2c95..77c405fd 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 c99bd9e5..0a68dd19 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 4238a054..98c14508 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 00000000..0b6d14c5 --- /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 35b60d1f..3c0a92c3 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 95f5f4ca..788aef4a 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 f9e5ad2c..751c6900 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 6d9c907c..c50700fb 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 f725b306..2201dfe1 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 5909bc58..99c529fe 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 265a41d5..91b41bc9 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 d9e773b9..524ba3ff 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 f03a0ba6..5915cba9 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 da4cf8e1..0986c015 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 8640e41b..9d956cde 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 c9ad2fb3..c2eba062 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 b4e3da5e..d9b5efeb 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 13fcc2b0..fa7b4c52 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 20d7e29f..c9faa7b0 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 9ae7c4ef..aa7d2657 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 111b2f0b..b938535e 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 b6d9e6b4..b285f646 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 ac3241f2..73420936 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 abc405d9..43c85c62 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 0274fc63..a4b7e512 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 1697fa86..d080a501 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 44cc14e3..a1b91dce 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 2b37979d..9ba2ff49 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 be6a1458..0447f8b0 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 8718fe2e..1ef843a0 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 1254c5cb..4ea86692 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 a6912367..4150604c 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 1e80ed16..745c98c7 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 87bf635d..34b7075a 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 937c5b69..8e1d8983 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 cb769d1e..3ee9251b 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 1b8fc476..2d4e2c78 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 f5e6be7f..62119192 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 fc3e1f31..ddcf0325 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 70d6afd8..902eeb93 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 210fbc20..dd9f1c6c 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 183a0458..a4680521 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 8a35d193..e85288e2 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 34973d30..079607ce 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 532dbeef..36d9943e 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 ccb88b0b..137354f5 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 00000000..cbdebcc2 --- /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 +}