// This is free and unencumbered software released into the public domain. // Anyone is free to copy, modify, publish, use, compile, sell, or // distribute this software, either in source code form or as a compiled // binary, for any purpose, commercial or non-commercial, and by any // means. // In jurisdictions that recognize copyright laws, the author or authors // of this software dedicate any and all copyright interest in the // software to the public domain. We make this dedication for the benefit // of the public at large and to the detriment of our heirs and // successors. We intend this dedication to be an overt act of // relinquishment in perpetuity of all present and future rights to this // software under copyright law. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. // IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR // OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, // ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR // OTHER DEALINGS IN THE SOFTWARE. // For more information, please refer to #ifndef MICROPROFILE_ENABLED #error "microprofile.h must be included before including microprofiledraw.h" #endif #ifndef MICROPROFILEDRAW_ENABLED #define MICROPROFILEDRAW_ENABLED MICROPROFILE_ENABLED #endif #ifndef MICROPROFILEDRAW_API #define MICROPROFILEDRAW_API #endif #if MICROPROFILEDRAW_ENABLED MICROPROFILEDRAW_API void MicroProfileDrawInitGL(); MICROPROFILEDRAW_API void MicroProfileRender(uint32_t nWidth, uint32_t nHeight, float fScale); MICROPROFILEDRAW_API void MicroProfileBeginDraw(uint32_t nWidth, uint32_t nHeight, float* pfProjection); MICROPROFILEDRAW_API void MicroProfileBeginDraw(uint32_t nWidth, uint32_t nHeight, float fScale); MICROPROFILEDRAW_API void MicroProfileEndDraw(); #ifdef MICROPROFILEDRAW_IMPL struct MicroProfileDrawVertex { float nX; float nY; uint32_t nColor; float fU; float fV; }; struct MicroProfileDrawCommand { uint32_t nCommand; uint32_t nNumVertices; }; struct MicroProfileDrawContext { enum { MAX_COMMANDS = 32, MAX_VERTICES = 16384, }; bool bInitialized; GLuint nVAO; GLuint nVertexBuffer; GLuint nProgram; GLuint nTexture; int nAttributePosition; int nAttributeColor; int nAttributeTexture; int nUniformProjectionMatrix; uint32_t nVertexPos; uint32_t nCommandPos; MicroProfileDrawVertex nVertices[MAX_VERTICES]; MicroProfileDrawCommand nCommands[MAX_COMMANDS]; }; MicroProfileDrawContext g_MicroProfileDraw; #define Q0(d, member, v) d[0].member = v #define Q1(d, member, v) d[1].member = v; d[3].member = v #define Q2(d, member, v) d[4].member = v #define Q3(d, member, v) d[2].member = v; d[5].member = v #define FONT_TEX_X 1024 #define FONT_TEX_Y 9 #define FONT_SIZE (FONT_TEX_X*FONT_TEX_Y * 4) namespace { extern const uint8_t g_MicroProfileFont[]; extern const uint16_t g_MicroProfileFontDescription[]; extern const char g_MicroProfileVertexShader_110[]; extern const char g_MicroProfileFragmentShader_110[]; extern const char g_MicroProfileVertexShader_150[]; extern const char g_MicroProfileFragmentShader_150[]; } bool MicroProfileCompileShader(GLuint* pnHandle, int nType, const char* pShader) { *pnHandle = glCreateShader(nType); glShaderSource(*pnHandle, 1, &pShader, 0); glCompileShader(*pnHandle); GLint compiled = 0; glGetShaderiv(*pnHandle, GL_COMPILE_STATUS, &compiled); if(!compiled) { char temp[4096]; glGetShaderInfoLog(*pnHandle, 4096, NULL, temp); printf("SHADER FAILED TO COMPILE:\n%s\n", temp); return false; } return true; } bool MicroProfileLinkProgram(GLuint* pnHandle, GLuint nVertexShader, GLuint nFragmentShader) { *pnHandle = glCreateProgram(); glAttachShader(*pnHandle, nVertexShader); glAttachShader(*pnHandle, nFragmentShader); glLinkProgram(*pnHandle); GLint linked = 0; glGetProgramiv(*pnHandle, GL_LINK_STATUS, &linked); if(!linked) { char temp[4096]; glGetProgramInfoLog(*pnHandle, 4096, NULL, temp); printf("PROGRAM FAILED TO LINK:\n%s\n", temp); return false; } return true; } void MicroProfileDrawInitGL() { MicroProfileDrawContext& S = g_MicroProfileDraw; MP_ASSERT(!S.bInitialized); const GLubyte* pGLVersion = glGetString(GL_VERSION); const GLubyte* pGLSLVersion = glGetString(GL_SHADING_LANGUAGE_VERSION); int nGLVersion = (pGLVersion[0] - '0') * 10 + (pGLVersion[2] - '0'); int nGLSLVersion = (pGLSLVersion[0] - '0') * 100 + (pGLSLVersion[2] - '0') * 10 + (pGLSLVersion[3] - '0'); glGenBuffers(1, &S.nVertexBuffer); glBindBuffer(GL_ARRAY_BUFFER, S.nVertexBuffer); glBufferData(GL_ARRAY_BUFFER, sizeof(S.nVertices), 0, GL_STREAM_DRAW); glBindBuffer(GL_ARRAY_BUFFER, 0); if (nGLVersion >= 3) glGenVertexArrays(1, &S.nVAO); else S.nVAO = 0; GLuint nVertexShader; if(!MicroProfileCompileShader(&nVertexShader, GL_VERTEX_SHADER, nGLSLVersion >= 150 ? g_MicroProfileVertexShader_150 : g_MicroProfileVertexShader_110)) return; GLuint nFragmentShader; if(!MicroProfileCompileShader(&nFragmentShader, GL_FRAGMENT_SHADER, nGLSLVersion >= 150 ? g_MicroProfileFragmentShader_150 : g_MicroProfileFragmentShader_110)) return; if(!MicroProfileLinkProgram(&S.nProgram, nVertexShader, nFragmentShader)) return; S.nAttributePosition = glGetAttribLocation(S.nProgram, "VertexIn"); S.nAttributeColor = glGetAttribLocation(S.nProgram, "ColorIn"); S.nAttributeTexture = glGetAttribLocation(S.nProgram, "TCIn"); S.nUniformProjectionMatrix = glGetUniformLocation(S.nProgram, "ProjectionMatrix"); glUseProgram(S.nProgram); glUniform1i(glGetUniformLocation(S.nProgram, "Texture"), 0); glUniform1f(glGetUniformLocation(S.nProgram, "RcpFontHeight"), 1.f / FONT_TEX_Y); glUseProgram(0); uint32_t* pUnpacked = (uint32_t*)alloca(FONT_SIZE); int idx = 0; int end = FONT_TEX_X * FONT_TEX_Y / 8; for(int i = 0; i < end; i++) { unsigned char pValue = g_MicroProfileFont[i]; for(int j = 0; j < 8; ++j) { pUnpacked[idx++] = pValue & 0x80 ? (uint32_t)-1 : 0; pValue <<= 1; } } pUnpacked[idx-1] = 0xffffffff; uint32_t* p4 = &pUnpacked[0]; glGenTextures(1, &S.nTexture); glBindTexture(GL_TEXTURE_2D, S.nTexture); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, FONT_TEX_X, FONT_TEX_Y, 0, GL_RGBA, GL_UNSIGNED_BYTE, &p4[0]); glBindTexture(GL_TEXTURE_2D, 0); S.bInitialized = true; } void MicroProfileBeginDraw(uint32_t nWidth, uint32_t nHeight, float* pfProjection) { (void)nWidth; (void)nHeight; MicroProfileDrawContext& S = g_MicroProfileDraw; if (!S.bInitialized) return; glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glDisable(GL_DEPTH_TEST); glDisable(GL_CULL_FACE); if (S.nVAO) glBindVertexArray(S.nVAO); glUseProgram(S.nProgram); glUniformMatrix4fv(S.nUniformProjectionMatrix, 1, 0, pfProjection); glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, S.nTexture); glBindBuffer(GL_ARRAY_BUFFER, S.nVertexBuffer); int nStride = sizeof(MicroProfileDrawVertex); glVertexAttribPointer(S.nAttributePosition, 2, GL_FLOAT, 0, nStride, (void*)(offsetof(MicroProfileDrawVertex, nX))); glVertexAttribPointer(S.nAttributeColor, 4, GL_UNSIGNED_BYTE, GL_TRUE, nStride, (void*)(offsetof(MicroProfileDrawVertex, nColor))); glVertexAttribPointer(S.nAttributeTexture, 2, GL_FLOAT, 0, nStride, (void*)(offsetof(MicroProfileDrawVertex, fU))); glEnableVertexAttribArray(S.nAttributePosition); glEnableVertexAttribArray(S.nAttributeColor); glEnableVertexAttribArray(S.nAttributeTexture); S.nVertexPos = 0; S.nCommandPos = 0; } void MicroProfileBeginDraw(uint32_t nWidth, uint32_t nHeight, float fScale) { MicroProfileDrawContext& S = g_MicroProfileDraw; if (!S.bInitialized) return; float left = 0.f; float right = nWidth / fScale; float bottom = nHeight / fScale; float top = 0.f; float near_plane = -1.f; float far_plane = 1.f; float projection[16] = {}; projection[0] = 2.0f / (right - left); projection[5] = 2.0f / (top - bottom); projection[10] = -2.0f / (far_plane - near_plane); projection[12] = - (right + left) / (right - left); projection[13] = - (top + bottom) / (top - bottom); projection[14] = - (far_plane + near_plane) / (far_plane - near_plane); projection[15] = 1.f; MicroProfileBeginDraw(nWidth, nHeight, projection); } void MicroProfileFlush() { MicroProfileDrawContext& S = g_MicroProfileDraw; if(S.nVertexPos == 0) return; MICROPROFILE_SCOPEI("MicroProfile", "Flush", 0xffff3456); glBufferSubData(GL_ARRAY_BUFFER, 0, S.nVertexPos * sizeof(MicroProfileDrawVertex), S.nVertices); int nOffset = 0; for(int i = 0; i < int(S.nCommandPos); ++i) { int nCount = S.nCommands[i].nNumVertices; glDrawArrays(S.nCommands[i].nCommand, nOffset, nCount); nOffset += nCount; } S.nVertexPos = 0; S.nCommandPos = 0; } MicroProfileDrawVertex* MicroProfilePushVertices(uint32_t nCommand, int nCount) { MP_ASSERT(nCount <= MicroProfileDrawContext::MAX_VERTICES); MicroProfileDrawContext& S = g_MicroProfileDraw; if(S.nVertexPos + nCount > MicroProfileDrawContext::MAX_VERTICES) MicroProfileFlush(); if(S.nCommandPos && S.nCommands[S.nCommandPos-1].nCommand == nCommand) { S.nCommands[S.nCommandPos-1].nNumVertices += nCount; } else { if (S.nCommandPos == MicroProfileDrawContext::MAX_COMMANDS) MicroProfileFlush(); S.nCommands[S.nCommandPos].nCommand = nCommand; S.nCommands[S.nCommandPos].nNumVertices = nCount; S.nCommandPos++; } uint32_t nOut = S.nVertexPos; S.nVertexPos += nCount; return &S.nVertices[nOut]; } void MicroProfileEndDraw() { MicroProfileDrawContext& S = g_MicroProfileDraw; if (!S.bInitialized) return; MicroProfileFlush(); glDisableVertexAttribArray(S.nAttributePosition); glDisableVertexAttribArray(S.nAttributeColor); glDisableVertexAttribArray(S.nAttributeTexture); glBindBuffer(GL_ARRAY_BUFFER, 0); glUseProgram(0); if (S.nVAO) glBindVertexArray(0); glDisable(GL_BLEND); } void MicroProfileRender(uint32_t nWidth, uint32_t nHeight, float fScale) { MicroProfileBeginDraw(nWidth, nHeight, fScale); MicroProfileDraw(nWidth, nHeight); MicroProfileEndDraw(); } void MicroProfileDrawText(int nX, int nY, uint32_t nColor, const char* pText, uint32_t nLen) { MICROPROFILE_SCOPEI("MicroProfile", "TextDraw", 0xff88ee); const float fOffsetU = 5.f / 1024.f; MP_ASSERT(nLen <= strlen(pText)); float fX = (float)nX; float fY = (float)nY; float fY2 = fY + (MICROPROFILE_TEXT_HEIGHT+1); MicroProfileDrawVertex* pVertex = MicroProfilePushVertices(GL_TRIANGLES, 6 * nLen); if (!pVertex) return; const char* pStr = pText; nColor = 0xff000000|((nColor&0xff)<<16)|(nColor&0xff00)|((nColor>>16)&0xff); for(uint32_t j = 0; j < nLen; ++j) { int16_t nOffset = g_MicroProfileFontDescription[uint8_t(*pStr++)]; float fOffset = nOffset / 1024.f; Q0(pVertex,nX, fX); Q0(pVertex,nY, fY); Q0(pVertex,nColor, nColor); Q0(pVertex,fU, fOffset); Q0(pVertex,fV, 0.f); Q1(pVertex, nX, fX+MICROPROFILE_TEXT_WIDTH); Q1(pVertex, nY, fY); Q1(pVertex, nColor, nColor); Q1(pVertex, fU, fOffset+fOffsetU); Q1(pVertex, fV, 0.f); Q2(pVertex, nX, fX+MICROPROFILE_TEXT_WIDTH); Q2(pVertex, nY, fY2); Q2(pVertex, nColor, nColor); Q2(pVertex, fU, fOffset+fOffsetU); Q2(pVertex, fV, 1.f); Q3(pVertex, nX, fX); Q3(pVertex, nY, fY2); Q3(pVertex, nColor, nColor); Q3(pVertex, fU, fOffset); Q3(pVertex, fV, 1.f); fX += MICROPROFILE_TEXT_WIDTH+1; pVertex += 6; } } void MicroProfileDrawBox(int nX0, int nY0, int nX1, int nY1, uint32_t nColor, MicroProfileBoxType Type) { MicroProfileDrawVertex* pVertex = MicroProfilePushVertices(GL_TRIANGLES, 6); if (!pVertex) return; if(Type == MicroProfileBoxTypeFlat) { nColor = ((nColor&0xff)<<16)|((nColor>>16)&0xff)|(0xff00ff00&nColor); Q0(pVertex, nX, (float)nX0); Q0(pVertex, nY, (float)nY0); Q0(pVertex, nColor, nColor); Q0(pVertex, fU, 2.f); Q0(pVertex, fV, 2.f); Q1(pVertex, nX, (float)nX1); Q1(pVertex, nY, (float)nY0); Q1(pVertex, nColor, nColor); Q1(pVertex, fU, 2.f); Q1(pVertex, fV, 2.f); Q2(pVertex, nX, (float)nX1); Q2(pVertex, nY, (float)nY1); Q2(pVertex, nColor, nColor); Q2(pVertex, fU, 2.f); Q2(pVertex, fV, 2.f); Q3(pVertex, nX, (float)nX0); Q3(pVertex, nY, (float)nY1); Q3(pVertex, nColor, nColor); Q3(pVertex, fU, 2.f); Q3(pVertex, fV, 2.f); } else { uint32_t r = 0xff & (nColor>>16); uint32_t g = 0xff & (nColor>>8); uint32_t b = 0xff & nColor; uint32_t nMax = MicroProfileMax(MicroProfileMax(MicroProfileMax(r, g), b), 30u); uint32_t nMin = MicroProfileMin(MicroProfileMin(MicroProfileMin(r, g), b), 180u); uint32_t r0 = 0xff & ((r + nMax)/2); uint32_t g0 = 0xff & ((g + nMax)/2); uint32_t b0 = 0xff & ((b + nMax)/2); uint32_t r1 = 0xff & ((r+nMin)/2); uint32_t g1 = 0xff & ((g+nMin)/2); uint32_t b1 = 0xff & ((b+nMin)/2); uint32_t nColor0 = (r0<<0)|(g0<<8)|(b0<<16)|(0xff000000&nColor); uint32_t nColor1 = (r1<<0)|(g1<<8)|(b1<<16)|(0xff000000&nColor); Q0(pVertex, nX, (float)nX0); Q0(pVertex, nY, (float)nY0); Q0(pVertex, nColor, nColor0); Q0(pVertex, fU, 2.f); Q0(pVertex, fV, 2.f); Q1(pVertex, nX, (float)nX1); Q1(pVertex, nY, (float)nY0); Q1(pVertex, nColor, nColor0); Q1(pVertex, fU, 3.f); Q1(pVertex, fV, 2.f); Q2(pVertex, nX, (float)nX1); Q2(pVertex, nY, (float)nY1); Q2(pVertex, nColor, nColor1); Q2(pVertex, fU, 3.f); Q2(pVertex, fV, 3.f); Q3(pVertex, nX, (float)nX0); Q3(pVertex, nY, (float)nY1); Q3(pVertex, nColor, nColor1); Q3(pVertex, fU, 2.f); Q3(pVertex, fV, 3.f); } } void MicroProfileDrawLine2D(uint32_t nVertices, float* pVertices, uint32_t nColor) { if(!nVertices) return; MicroProfileDrawVertex* pVertex = MicroProfilePushVertices(GL_LINES, 2*(nVertices-1)); nColor = ((nColor&0xff)<<16)|(nColor&0xff00ff00)|((nColor>>16)&0xff); for(uint32_t i = 0; i < nVertices-1; ++i) { pVertex[0].nX = pVertices[i*2]; pVertex[0].nY = pVertices[i*2+1] ; pVertex[0].nColor = nColor; pVertex[0].fU = 2.f; pVertex[0].fV = 2.f; pVertex[1].nX = pVertices[(i+1)*2]; pVertex[1].nY = pVertices[(i+1)*2+1] ; pVertex[1].nColor = nColor; pVertex[1].fU = 2.f; pVertex[1].fV = 2.f; pVertex += 2; } } namespace { const char g_MicroProfileVertexShader_110[] = "#version 110\n\ uniform mat4 ProjectionMatrix; \ attribute vec3 VertexIn; attribute vec4 ColorIn; attribute vec2 TCIn; \ varying vec2 TC; varying vec4 Color; \ void main() { Color = ColorIn; TC = TCIn; gl_Position = ProjectionMatrix * vec4(VertexIn, 1.0); }"; const char g_MicroProfileVertexShader_150[] = "#version 150\n\ uniform mat4 ProjectionMatrix; \ in vec3 VertexIn; in vec4 ColorIn; in vec2 TCIn; \ out vec2 TC; out vec4 Color; \ void main() { Color = ColorIn; TC = TCIn; gl_Position = ProjectionMatrix * vec4(VertexIn, 1.0); }"; const char g_MicroProfileFragmentShader_110[] = "#version 110\n\ uniform sampler2D Texture; uniform float RcpFontHeight; \ varying vec2 TC; varying vec4 Color; \ void main() { \ vec4 c0 = texture2D(Texture, TC.xy); \ vec4 c1 = texture2D(Texture, TC.xy + vec2(0.0, RcpFontHeight)); \ gl_FragColor = c0.w < 0.5 ? vec4(0, 0, 0, c1.w) : c0 * Color; \ } \ "; const char g_MicroProfileFragmentShader_150[] = "#version 150\n\ uniform sampler2D Texture; uniform float RcpFontHeight; \ in vec2 TC; in vec4 Color; \ out vec4 result; \ void main() { \ vec4 c0 = texture(Texture, TC.xy); \ vec4 c1 = texture(Texture, TC.xy + vec2(0.0, RcpFontHeight)); \ result = c0.w < 0.5 ? vec4(0, 0, 0, c1.w) : c0 * Color; \ } \ "; const uint16_t g_MicroProfileFontDescription[] = { 0x0ce,0x0ce,0x0ce,0x0ce,0x0ce,0x0ce,0x0ce,0x0ce,0x0ce,0x0ce,0x0ce,0x0ce,0x0ce,0x0ce,0x0ce,0x0ce, 0x0ce,0x0ce,0x0ce,0x0ce,0x0ce,0x0ce,0x0ce,0x0ce,0x0ce,0x0ce,0x0ce,0x0ce,0x0ce,0x0ce,0x0ce,0x0ce, 0x0ce,0x201,0x209,0x211,0x219,0x221,0x229,0x231,0x239,0x241,0x249,0x251,0x259,0x261,0x269,0x271, 0x1b1,0x1b9,0x1c1,0x1c9,0x1d1,0x1d9,0x1e1,0x1e9,0x1f1,0x1f9,0x279,0x281,0x289,0x291,0x299,0x2a1, 0x2a9,0x001,0x009,0x011,0x019,0x021,0x029,0x031,0x039,0x041,0x049,0x051,0x059,0x061,0x069,0x071, 0x079,0x081,0x089,0x091,0x099,0x0a1,0x0a9,0x0b1,0x0b9,0x0c1,0x0c9,0x2b1,0x2b9,0x2c1,0x2c9,0x2d1, 0x0ce,0x0d9,0x0e1,0x0e9,0x0f1,0x0f9,0x101,0x109,0x111,0x119,0x121,0x129,0x131,0x139,0x141,0x149, 0x151,0x159,0x161,0x169,0x171,0x179,0x181,0x189,0x191,0x199,0x1a1,0x2d9,0x2e1,0x2e9,0x2f1,0x0ce, 0x0ce,0x0ce,0x0ce,0x0ce,0x0ce,0x0ce,0x0ce,0x0ce,0x0ce,0x0ce,0x0ce,0x0ce,0x0ce,0x0ce,0x0ce,0x0ce, 0x0ce,0x0ce,0x0ce,0x0ce,0x0ce,0x0ce,0x0ce,0x0ce,0x0ce,0x0ce,0x0ce,0x0ce,0x0ce,0x0ce,0x0ce,0x0ce, 0x0ce,0x0ce,0x0ce,0x0ce,0x0ce,0x0ce,0x0ce,0x0ce,0x0ce,0x0ce,0x0ce,0x0ce,0x0ce,0x0ce,0x0ce,0x0ce, 0x0ce,0x0ce,0x0ce,0x0ce,0x0ce,0x0ce,0x0ce,0x0ce,0x0ce,0x0ce,0x0ce,0x0ce,0x0ce,0x0ce,0x0ce,0x0ce, 0x0ce,0x0ce,0x0ce,0x0ce,0x0ce,0x0ce,0x0ce,0x0ce,0x0ce,0x0ce,0x0ce,0x0ce,0x0ce,0x0ce,0x0ce,0x0ce, 0x0ce,0x0ce,0x0ce,0x0ce,0x0ce,0x0ce,0x0ce,0x0ce,0x0ce,0x0ce,0x0ce,0x0ce,0x0ce,0x0ce,0x0ce,0x0ce, 0x0ce,0x0ce,0x0ce,0x0ce,0x0ce,0x0ce,0x0ce,0x0ce,0x0ce,0x0ce,0x0ce,0x0ce,0x0ce,0x0ce,0x0ce,0x0ce, 0x0ce,0x0ce,0x0ce,0x0ce,0x0ce,0x0ce,0x0ce,0x0ce,0x0ce,0x0ce,0x0ce,0x0ce,0x0ce,0x0ce,0x0ce,0x0ce, }; const uint8_t g_MicroProfileFont[] = { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x10,0x78,0x38,0x78,0x7c,0x7c,0x3c,0x44,0x38,0x04,0x44,0x40,0x44,0x44,0x38,0x78, 0x38,0x78,0x38,0x7c,0x44,0x44,0x44,0x44,0x44,0x7c,0x00,0x00,0x40,0x00,0x04,0x00, 0x18,0x00,0x40,0x10,0x08,0x40,0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x10,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x38,0x10,0x38,0x7c,0x08,0x7c,0x1c,0x7c,0x38,0x38, 0x10,0x28,0x28,0x10,0x00,0x20,0x10,0x08,0x10,0x10,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x04,0x00,0x20,0x38,0x38,0x70,0x00,0x1c,0x10,0x00,0x1c,0x10,0x70,0x30,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x28,0x44,0x44,0x44,0x40,0x40,0x40,0x44,0x10,0x04,0x48,0x40,0x6c,0x44,0x44,0x44, 0x44,0x44,0x44,0x10,0x44,0x44,0x44,0x44,0x44,0x04,0x00,0x00,0x40,0x00,0x04,0x00, 0x24,0x00,0x40,0x00,0x00,0x40,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x10,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x44,0x30,0x44,0x04,0x18,0x40,0x20,0x04,0x44,0x44, 0x10,0x28,0x28,0x3c,0x44,0x50,0x10,0x10,0x08,0x54,0x10,0x00,0x00,0x00,0x04,0x00, 0x00,0x08,0x00,0x10,0x44,0x44,0x40,0x40,0x04,0x28,0x00,0x30,0x10,0x18,0x58,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x44,0x44,0x40,0x44,0x40,0x40,0x40,0x44,0x10,0x04,0x50,0x40,0x54,0x64,0x44,0x44, 0x44,0x44,0x40,0x10,0x44,0x44,0x44,0x28,0x28,0x08,0x00,0x38,0x78,0x3c,0x3c,0x38, 0x20,0x38,0x78,0x30,0x18,0x44,0x10,0x6c,0x78,0x38,0x78,0x3c,0x5c,0x3c,0x3c,0x44, 0x44,0x44,0x44,0x44,0x7c,0x00,0x4c,0x10,0x04,0x08,0x28,0x78,0x40,0x08,0x44,0x44, 0x10,0x00,0x7c,0x50,0x08,0x50,0x00,0x20,0x04,0x38,0x10,0x00,0x00,0x00,0x08,0x10, 0x10,0x10,0x7c,0x08,0x08,0x54,0x40,0x20,0x04,0x44,0x00,0x30,0x10,0x18,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x44,0x78,0x40,0x44,0x78,0x78,0x40,0x7c,0x10,0x04,0x60,0x40,0x54,0x54,0x44,0x78, 0x44,0x78,0x38,0x10,0x44,0x44,0x54,0x10,0x10,0x10,0x00,0x04,0x44,0x40,0x44,0x44, 0x78,0x44,0x44,0x10,0x08,0x48,0x10,0x54,0x44,0x44,0x44,0x44,0x60,0x40,0x10,0x44, 0x44,0x44,0x28,0x44,0x08,0x00,0x54,0x10,0x18,0x18,0x48,0x04,0x78,0x10,0x38,0x3c, 0x10,0x00,0x28,0x38,0x10,0x20,0x00,0x20,0x04,0x10,0x7c,0x00,0x7c,0x00,0x10,0x00, 0x00,0x20,0x00,0x04,0x10,0x5c,0x40,0x10,0x04,0x00,0x00,0x60,0x10,0x0c,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x7c,0x44,0x40,0x44,0x40,0x40,0x4c,0x44,0x10,0x04,0x50,0x40,0x44,0x4c,0x44,0x40, 0x54,0x50,0x04,0x10,0x44,0x44,0x54,0x28,0x10,0x20,0x00,0x3c,0x44,0x40,0x44,0x7c, 0x20,0x44,0x44,0x10,0x08,0x70,0x10,0x54,0x44,0x44,0x44,0x44,0x40,0x38,0x10,0x44, 0x44,0x54,0x10,0x44,0x10,0x00,0x64,0x10,0x20,0x04,0x7c,0x04,0x44,0x20,0x44,0x04, 0x10,0x00,0x7c,0x14,0x20,0x54,0x00,0x20,0x04,0x38,0x10,0x10,0x00,0x00,0x20,0x10, 0x10,0x10,0x7c,0x08,0x10,0x58,0x40,0x08,0x04,0x00,0x00,0x30,0x10,0x18,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x44,0x44,0x44,0x44,0x40,0x40,0x44,0x44,0x10,0x44,0x48,0x40,0x44,0x44,0x44,0x40, 0x48,0x48,0x44,0x10,0x44,0x28,0x6c,0x44,0x10,0x40,0x00,0x44,0x44,0x40,0x44,0x40, 0x20,0x3c,0x44,0x10,0x08,0x48,0x10,0x54,0x44,0x44,0x44,0x44,0x40,0x04,0x12,0x4c, 0x28,0x54,0x28,0x3c,0x20,0x00,0x44,0x10,0x40,0x44,0x08,0x44,0x44,0x20,0x44,0x08, 0x00,0x00,0x28,0x78,0x44,0x48,0x00,0x10,0x08,0x54,0x10,0x10,0x00,0x00,0x40,0x00, 0x10,0x08,0x00,0x10,0x00,0x40,0x40,0x04,0x04,0x00,0x00,0x30,0x10,0x18,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x44,0x78,0x38,0x78,0x7c,0x40,0x3c,0x44,0x38,0x38,0x44,0x7c,0x44,0x44,0x38,0x40, 0x34,0x44,0x38,0x10,0x38,0x10,0x44,0x44,0x10,0x7c,0x00,0x3c,0x78,0x3c,0x3c,0x3c, 0x20,0x04,0x44,0x38,0x48,0x44,0x38,0x44,0x44,0x38,0x78,0x3c,0x40,0x78,0x0c,0x34, 0x10,0x6c,0x44,0x04,0x7c,0x00,0x38,0x38,0x7c,0x38,0x08,0x38,0x38,0x20,0x38,0x70, 0x10,0x00,0x28,0x10,0x00,0x34,0x00,0x08,0x10,0x10,0x00,0x20,0x00,0x10,0x00,0x00, 0x20,0x04,0x00,0x20,0x10,0x3c,0x70,0x00,0x1c,0x00,0x7c,0x1c,0x10,0x70,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x38,0x00,0x00,0x30,0x00,0x00,0x00,0x00,0x00,0x40,0x04,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x38,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, }; } #endif #endif