Analyzing special font files

Everything else that doesn't fall into one of the other PB categories.
User avatar
Michael Vogel
Addict
Addict
Posts: 2680
Joined: Thu Feb 09, 2006 11:27 pm
Contact:

Analyzing special font files

Post by Michael Vogel »

I wrote some apps for sport watches from Garmin using the Connect IQ SDK which uses a simple programming language called monkey C...
Programming is fun and I also wrote a small windows tool to deal with all things, so everything needed to write an app is java, the extracted SDK and a text editor.

Anyhow there's an annoying point - the enclosed simulator uses font files (.monkeyface) which don't match exactly with the original watch fonts sometimes...
...so I want to explore what's inside the font files. I think, I know quite a lot of things for now, but I can't get the complete picture - so maybe some of you are experts in solving logical puzzles :wink:

What I (believe to) know:
The font file header seems to contain 4 byte values, starting with an ID (00240306), followed by the filesize and three pointers (*Table1, *Table2, *Bitmap) and three more values. After that another magic number is seen (12345678) before table 1, table2 and the bitmap data starts.

Image

I have no idea about table 1, table 2 seems to contain pointers to the character data (relative to the bitmap pointer). But the most mysterious thing is the bitmap data itself:

Taking the 364th entry of the table 2 in a font called 'Noto Sans 40' says 76F7801B, taking the first part (76F7) together with the bitmap pointer 0001AA34 the location of this character should be 0x2212B. I believe, 1B could be the character width, but that's another story.
Here's the hex dump of this file part:
Image

When two bits are seen as a single pixel, the following result appears (the first four pixels are the byte at the file offset 0x2211E, so the last four pixels in the second row ar at 0x2212B):
Remark: I cutted the image so two pixel columns are seen, the real data order within the font file is symbol (10), (11), (12), (13) and so on...
Image

As you can see, the characters don't look perfect because the line width seems to change within the symbols :shock:
Any idea what's missing?
User avatar
Thorsten1867
Addict
Addict
Posts: 1366
Joined: Wed Aug 24, 2005 4:02 pm
Location: Germany

Re: Analyzing special font files

Post by Thorsten1867 »

Translated with http://www.DeepL.com/Translator

Download of PureBasic - Modules
Download of PureBasic - Programs

[Windows 11 x64] [PB V5.7x]
User avatar
Michael Vogel
Addict
Addict
Posts: 2680
Joined: Thu Feb 09, 2006 11:27 pm
Contact:

Re: Analyzing special font files

Post by Michael Vogel »

Attention, the monkeyface font has it's very special (non vector) file format and I didn't find any documentation about it.

One more note about the decoding as mentioned in the initial posting - the pixel data needs to be interpreted in a reversed order (0x03 means the leftmost pixel is black)...
User avatar
Michael Vogel
Addict
Addict
Posts: 2680
Joined: Thu Feb 09, 2006 11:27 pm
Contact:

Re: Analyzing special font files

Post by Michael Vogel »

Still not sure how to decode these fonts - someone told me that a RLE compression is used but there' no standard RLE method for dealing with 2 bits for a pixel.

Meantime I was able to compress 4 glyphs of a font and have the result as well, but even now I am not able to decompress the data to get the original glyphs. So binary experts are needed now :)

Couldn't upload the screenshots of the original font / compressed font / delta comparisn - but if anyone is interested the images can be saved using the following snippets

Here's an example of a user font source bitmap:

Code: Select all

CompilerIf #PB_Compiler_Version>555:Macro Base64Decoder(a,b,c,d):Base64DecoderBuffer(a,b,c,d):EndMacro:CompilerEndIf
M=?E-?S:R=AllocateMemory(M):If R:B=Base64Decoder(?S,M,R,M):Z=575:If B:X=AllocateMemory(Z):F.s=SaveFileRequester("Save","IQ FontSource.png","Alle Dateien (*.*)",0):If F And UseZipPacker() And UncompressMemory(R,B,X,Z)=Z:CreateFile(0,F):WriteData(0,X,Z):EndIf:EndIf:EndIf
DataSection
S:
!db 'eJzrDPBz5+WS4mJgYOD19HAJAtI1QCzLwgwkZ80QLQJS7CWevq7sj1nY2KQFvZ+s9QIKcRZ4RBYzMMgdBGHGw5khwUBBlnRHX0cGho393H8SWYF8gwCfEFcgHRoaumrVqv9AwEAYqV5NnMTAwDjJ08UxpOLW0qmJSc0KPK3COxy0xBOeMmW8q9+u2qiw6+rOafLX1u9jV2vhSGB+aPHvKLdxfkm/PH/RtWjJzvn9Sz9ciP/0yVRi/q/wDP5L165e'
!db '3zOhMCzuS6N+cNHvvc/YRbh2KHCeZn306mXG5f8HU+YoMhh17D1hU/S0J/eXUVLdSVUe23WTuBSfyZTEfTmq8uLcxNI3Nq+Tp+Y29E4Iv7C9u/T+hnN572suqD86NCHQeOX7mcv+vrN508v/iyk7xVvQeUrCqRA/4dl7N74M/OJYYbzY7rbCk29Nyj/mnr0X2ZNl/vdVmS5zZ/XcN8Lmuws7tiX72r+JYfQvs7lpvdq2vPZtmabrleNfU9arV/Om'
!db 'rC7fu17vt8P3sPi02u3qM9ccN1v67voNz+Dnv6ZVTvF4kfYs85r4Zm8pzrx31QW1YttWMVkyXNDKW7er8+y8PVyz7V7vvVbyYOex86b2b3qbXzXPiUi1Dly7Kn6uxfb36gWXxIt8ln+23XxrLv+v8l29LH57b/c83bM9dvM3K8v1T/a+2+vHvfhy3Y3n9n9PHTiff+PuR97/YhES4pUTeoExyuDp6ueyzimhCQCdnA2P'
E:
EndDataSection
...And this is the compressed result (Not sure where the glyphs start And End):

Code: Select all

CompilerIf #PB_Compiler_Version>555:Macro Base64Decoder(a,b,c,d):Base64DecoderBuffer(a,b,c,d):EndMacro:CompilerEndIf
M=?E-?S:R=AllocateMemory(M):If R:B=Base64Decoder(?S,M,R,M):Z=3405:If B:X=AllocateMemory(Z):F.s=SaveFileRequester("Save","IQ FontCompressed.png","Alle Dateien (*.*)",0):If F And UseZipPacker() And UncompressMemory(R,B,X,Z)=Z:CreateFile(0,F):WriteData(0,X,Z):EndIf:EndIf:EndIf
DataSection
S:
!db 'eJxNV3tckmcbdq1ynda+yrWOVla0nFo6JyLgTM1cKqYSJaLrNJaapIiISXx91jqqLbTSQLIsARVy/owJAuugphbOQjANyARJUJgCknjo04rX/cHv5ffyPPd9X9d93dfzcD4yImTR/JXzHRwcFoXuCoqaeuY7OHxG/2LW1LeyX3mvpx5b04P3pQemHTmQfhSXsi7m6LEjDtEH1v2wLuB42jrPbdt9120DQzy9Idu2r3Pdtn3btsWR30xvdkwPDQ92'
!db '7J09d+7KLYtsyz6fejXv+K79eAeHBUumP589V5wcn3o5GxsQHuDgUJ2/YPzAHAeHhXdDgwJiMrsG6XvyVvkuDCJ+faJBfbl5fQ1lnmNn7LJgNvUP1ZjnQoGb4DdM4Plb8MmuvqZ8Z39nyoTNou01qsTvs8cHu3nvs0VwDpj7flizWw8hJEuILHmlEclAM1D5/nB4rHhQVYV6ZNQwZBUdqmKbIJrSK7HoVfSljlsnt+ogFqMwvnxsZbCVGPkVOvTm'
!db '3iXMwiAj5UqWmGNNDZY/KrBKtYL3IUiPAvHD18UWoeT9HUnSssfTy2Ynbmpv5RWgWNkVnkNltixNoE6oIxHWYEWBuU1F14rU8fZlqSW4cENrhLJP/WOL11bJ6tvFn9PepVp9Utfdv/Jj1cZI1/MlOCSflI+nV9VuP0P1Z2Xvzo3GhLRjxBygJlxJZIfLFm5a4mp++kSoJqPFS3qCbmRCm5u7V5+bjjFP+tObFJFGWhF7+3sZU9p1Jdq5R+oIqbsZ'
!db '3e13qvOnWbXTqTJ0nrRaxoWui+0NQ3OR4nKlXn1OArk6fFTnqZwjnV7UyQXFMLMbiqz6vGdFi9NFKKsf24g+QNZj7JX6mnCFBj7qjt6HWgduyheI7jTKFDVx6/+FZbMJQx3fqXGNWFujuaarSclEnrFXINF78sEn7vNrFyvinXyysExbXtYa7z53O1dDNFw4tLdRqawaApMK2fKfyfrCgA9x6aJsTIo6XsE3GeD3QsUBIBAe4I8+gabCl+uK0x7v'
!db 'NmVecOOytzAaefErPiACc1uZyYOIrlt6ZB4lmRwyghMu+JCq2l/uU+RPU6PzUOEj3yI6dbcDkjedip0m3I/wj09WYHrdIJLa9ZXtgdjl44aEaz3magVEX9adcyhK3zMQcNd//fgnXFqztD5OzuDjcyT6wqZXYB+Sp0cXANugFAh8qS+84gevdekcKS6IrmHowemeTf38tgrnW1fQu8kJ5FN8qamoux6m9e3H7wMIpZN2NHltxs5GZPkh74/4VSSl'
!db 'WBpmxNrGo9Ww+JNl0OZ+arei3JtljYZrzV8ou66FA2i850TkZgY/c5SNCaKXgvdfK5YugqjISWL8TFvacmmvuIU+YZLLMZY1iVA04b+JnChNnhptnJU4HYbGWNX/tJ9lWYsVcQSbyxpfX2piHYqJF3g7vv3RnqfNkoMypTnJqied7djAbTw+Fs/UVjB8x2irxfV7KMyTjtpkTZWwDZgOEaXiTeWe8PHKN9IV7KGwESrBBNJCmwFJpBJLjnv67Csy'
!db '3++EuJIqtA2HOYWAoCWr+0duXJcmhNk2QPBE9IQTzuy20c6cElpaY+wc2liuxGBqukNafA81DH1jqWNzogJEFvcP/D0enXTDYn7SuLPFguF6gxZO6rtao9xbZM7eYI9i4l9qJjVhuGkjGFYqBB6bWt/Sn6SRbsgAOmTKTqrgXulFSjJjvrSWkzrU0F/tBLyDWU5PbU0TGKA9V1EsOSoGA9ejuQs/kDowoGInkwr5eV0hcanD11Mo8bV5Gik73Rru'
!db 'ap/pg+XcFGE+Mckk1XeMl/RiqUNELQgZcZ/Qt3emedp5/pgjlwNfKdv0T1vDR7wRIg/T6U85zMNVF/DORNllPmGpUxOKv1amCFQ862CCspd/SHDL+l4UfcNQiSK0Be2Vv9QV6aUvEJLLAzLiFsBXsk+2sULe2qjDG7E4ox+NsMPe8TGYmY8dg5Bndazcx9sc2WO+xFCj0Vj3pYBtkXc/sxCMcifNoojFgWfYdarh/FDuV7rXqo9283b0Kr6NMAJF'
!db '0k7WFuqwLV4xdD67/a1t6LCHabadw04GaKCkTlNJZVn38msvKiz3EOKumzspUWgEIHHL6flYDi6JcRVvOG9zp9r+g4Ule3Jnhkgr0dGl85XMUmMfLEKRzcO6iCwtHxVAgu04ov8uP+XkiyqncfMz54Gm9kEEF/CWeMxOnntcjxkUw0Dj6SmwhsNPIyi5q8j3ttoFWl1jzHxuZXbzHg6VcfwV4M8b9h+67d77ybe0Mt6SiVCh9YVHJinlHkCddoy3'
!db 'mfD1BcPLDRjnqN502w/htvkQWABg5gcpJZGpj84uy1tM0LcL4EIkZQaMifQQRN5FNjD6Agur6h7Mr56uYiosVG59wDqPOnEWpL0B7Q9Ew6sAFBP4sILFm/oCeeTiCbv8oHJHmOKslCCt16izPebYo9C0aK46MBGqiys0dN7XuZ3/VNEtlGNCqqQlyppVvriUKgjTdXWYIhIWevetSop1Agbe3ydqezO1wAcMU9Ct7Il9VK/fO6xVjG4YKBiwV+2o'
!db '7BhFN/LkeuYNrz43SrH6AEAlJaXszc62l91CJd1LWPKqNRjosKiWEB9qrbkveZAmCZnEqHgAlUTTEosS4fKFP+WPMb8wADK+7TIq+3ge5435LwV7P7Exsijz8JmZk/C1kwVukH4H1palJ73tuN7xsrDlBtKYHyoMXW4Hk2kYd6st+d73ouuE0JxDOfJxGqCqqLoCPIWY1Z8x5sz23WmJL19Lbr2B9GACltVucqvNb6kT+8EyOl7RH+6/mMa5rayA'
!db '1voh/gRoNhtqFHGlgrl31+LaFa3QUYMOD/I++6+rBW3Uh+BhkP0aNrKD0ObHYcIeSka/U6TO2A49a0e5NUoO4qePVbo6I5MIEjBOfQ5oRed+FRtMTqZbIbULdTZF/d/9rtzGDBdulP3seByx5lSXKb13Eu4rTnQFVTBjL60Ses1MfUmkokkQr6GVDrwL58mPyR9JbTIq6RtAJ/KlGUa5gn/JQIpFg0/Ub8aXLp2xLf/SLpMfK8lY4pF9+25qWuP1'
!db 'YSgw9WCrGwGBUvaZ29997+miKs7M6T3gk8Zttq22xx6wgmiZ3eW/L8pCpOOLDZkFVnCdvKzJZSb3A9cUM6RYvWUpXxuq5JwH2UkhT1nqaO4Lr3t+kqriL7G4l18D50i8o/GfwylSy5MUzG9vmpUrANFRcSzlLsTIlcznFSkD32YACjKJ+JLRKB/ZHT68RxqXbmXA+pEAvU+ugwZkItzgM12WE5nQs9weSvFLawVfi44Q9Zb9EgRIfmyMt1UCB/l6'
!db '3k4YPCw+LmfQaG0vxcHiS8TP7B5OHzPmZj0ECdljfswhcJsf0KaTlIcte0Ua8/PBkXxi48uJ8NVG2r8PXW46uZVEDn7WGt6np8W+53CJgEQmSsKotDBNVAuOP0HqOAHyvbqyfLgudO3OmbHSqN15bUEllZhjQt6JzWmA+Du5OSjuHj2COtpoEHFaHrsg856Mov9Z8LGDCaoo7VGWHAy7RZsyI2uuglnHeIpYYi9ZcXJFBKfXfC4N+oikXHGj5hfZ'
!db 'YG11R0iOffxGTFXumPy6HsdEqGLtA8XQNsS7T26ch/PlokyHIiZ6ZCs7GH+vIs4CNCF/gCp5RdXf7FsvGLvbUfxqkAC2F/unQIQsUu/ExMTfqWfbkqauKap98hyW/ZA72MSTkhM023UWNDYCIrxJ09Kzq7tdLkye/nS9GXi3l5gwKIPHTd204KUjNBb5KO8jiZNz4KObKhf2/UWZ+gfjEBocEcTZ8fP//g+cMdPX'
E:
EndDataSection
User avatar
Michael Vogel
Addict
Addict
Posts: 2680
Joined: Thu Feb 09, 2006 11:27 pm
Contact:

Re: Analyzing special font files

Post by Michael Vogel »

Here's a closer look how some pixel lines have been changed from the original glyph (see posting above):

Code: Select all

CompilerIf #PB_Compiler_Version>555:Macro Base64Decoder(a,b,c,d):Base64DecoderBuffer(a,b,c,d):EndMacro:CompilerEndIf
M=?E-?S:R=AllocateMemory(M):If R:B=Base64Decoder(?S,M,R,M):Z=38026:If B:X=AllocateMemory(Z):F.s=SaveFileRequester("Save","MonkeyFaceCompression.png","Alle Dateien (*.*)",0):If F And UseZipPacker() And UncompressMemory(R,B,X,Z)=Z:CreateFile(0,F):WriteData(0,X,Z):EndIf:EndIf:EndIf
DataSection
S:
!db 'eJzsvHdUU+2276+vKCICSpeqVJEmIL0JCEivghAC0qUGEiBAKArSm/QeEER6kF4ioFTpvZdI76EndG7w3fvud5+zx/idc+8Yv7v/OGOEsdZ8staTZ86nzc/6JoRoqisS3aG5c+3aNSKlly+0r13Ds7t27Y+B23/gSsw7axdwhycu8q9d5MCWpi42IMeHujYOltd0QA+FH8o4gR/yP+UTffhURIxfSExA6CHnU76nT10Y3/Pi7sJ3UVKTx1/Aw8fH'
!db 'Y3p3r+8jrojA6aUB5No1QtKrv+uDMz5nuEI8axk1mWvXSqMIz0xvXrsWu6D0QkbXfXJzhkRXV99v+zRCK1raTy/kjy+6m08+C4a8dW0hDHFI+7bW9LZ6jasGkupD337AD1qOeNsHmAHx84K0EKkw2HKvJ4TitAdpWmnwZbtfkkqPLfJY7nCrgs83sxWtfUabUyBTfPuxXv5PxkuWPQzH8/dMZSHvez41ZLjqyaZDnLabpWAZ+4WQdd1u9owqAlwr'
!db 'r73z64D6Fnhvm7jq37qy2yo7zk2GR0fXESRXZrhJLH79Ra7vCTv3YXBIyIC2o7x8QAKY8M6dirhCFUvLnARw9tZ2USGjfCoa7ci9RElJacuhPyaSH4bYVdY/VaCNPDX3X7ho+WL3bbDSRJ4By26Tj39VcdJ9gqvOuaYbnXl1eE7xP+aVqTYKvN7zhJOzMg6gqZkJG7qepIoLOPpJOAdwAWJq+gmtFnVnZmamrvAehUjfjxf8PhhOhMz1q358Qkp+'
!db 'VUMe0/+Y/9ks6Kjj7C/MzHyuUhsfH18nLPlk1RbV1CTLvaSnq/uWg4qaqK5NCXiuTwVcsKiI0K/DWAO3CguNgCLoqIi3G4rRNbduXlVX8FLz6pAZivc/5n822TYQz0v8/P7ABVVPT+FVbd1Fb52uru4q4o83ngEBAXWFT7+4RMQOCBk70+ExpCF8PncdrTUa+V+tyNdesTy+OmjK+/2P+Z/N2KA02Hnvez5E0EYtOfdUIxqVa8OBpQLZj2gjEI3l'
!db 'PDniUFuOavdCOGakUloxtZTxEWx1MiPboXHyvKtxWBvte1LSd7Usu+dsuJM7nOvrn66XnZocHJgAT+MR+x36F87+CeDDSNoh9uIG8SC7f4/h9O9pspF4zpy3Y5d8GdelcpBm5osdwxYzr6h1SATThoEBfJXundaGnSOH0MiqcwMq3CJi5wvnXz4dUeQeq7DnwOUcbCSiwjxWpejQiOhXnD6ZOdPp4iqVcTB7+dQEMASsZ8sBlfOp2OyQjDxDF6Cf'
!db 'vAio4fbEFIZeXoSi1RiZQYy2A689By/dlbGMb1Trz8ZgrvrXsx9PTlYjkQCVWtwkM+z0RpYZqNRKu6Nhhp3pUjaVCWBmZyrGq7b/v16E/83MFIlV1+4x+CAwh49CxAsXs0twnrxKLSrdbEwb3fl4qsRlAJexpJrYTGbYmOASI/8OkgsN3I1vzk57Fy8zkXeyC8u1NWq7Uvcq4mB2ZXCBY4NKIe4lN1sOQa6GN9+73mpo3rx5k+QiKilv+h9bjf4Y'
!db '6gEuraqfnPQ37JR8DSjMmY4XFTXs7OkwyM+Z3vXv+/cIzr+1+eduXlamrVKLi7BhZ3FeXr+2o6pqOC4xJSSsjCvc2C6ya1xHo0e1edoUKrb6qGkH3M4iwOnmI5OVlfiV9r9603NwszTHfUPvau7WYQrT0uL9l8MTryb5Oy0Kab3aw7Lbbye++55u6uMuZG34lfh7+9rS373pT0YO3f2zHbCxzEgruuOD/X1Ya6NtfrvpFGNFnLi8xOccI+D8hVzR'
!db 'Vd6G4VRl2eyjJtrUxyUZmMK34n0DrrOIrvFt/a4bKGqw1FjmlWv/zxPP/7/NkUWkNLeDkdsCSbWQ/QkiwXOa2AuRM03EeWhfwgNsrMtH3jG3PS5H4Tq2YkufmjY89q8hnNjpWl1XxJ2//A/5g+Dxj0sCncKiomFtRxmZ9wlgJBKJy6Vfv6Z+9ff550PhkOXQOCg/dlREeE6VLTPmTuGwoh/eNxD4t43Pdkcwz1cyJ5fBF4diFzrh+UHPztNda992'
!db 'DGk7bmpL6hu4bvUNVJmsZdn5jgpKbTQ5m9o/NVazxw2x+rcdA9o8C/stlB6Wsf+zjV77533zfKbVc333uOMdWro16QQ9H381pS5YdYtzplMVccRzGtFiXRlH63Aaz1OHWdnmmS2ADbWTtweUftrY7nYXFMraOhJn3xfgXuKX0nDxby/sMFk3SRZ5wnl44AS8cwWkAC2tTzm4tbYp7wkuk9/C1QSpGBhpGGCbxGWikacDbkZvvBhor5L7pciM3VDk'
!db '0X9hnL7qhkvCXMau5vu1blOwg0MxWuzq/J1oiwsUij07GNbRUCOgHdlzDKq/vDiFEgLrXGzc3DB5lIb6+tCDVa2tgC+5uX3p4lBdwnqnOVkdnaEZWWb5EcYz2/E8SjFmVdCnaBcH2MGmobnJWxZuOeUDl8LdocRsC5KVGjpW353HHM9iEJDNVdFSxlNu+p2IurLNDx8+aHE3ZGfLUaJ8I884QdM1zrqEM+XWUWdydry6xENR0hdHeZRPOqJPLjhf'
!db '9DEawc/TJGFuuoTAr2/eS1wfNMZ9zEgwHKii8im64i7HwFBxm5JJJFwybWGPGiQeEGmLK04zV+wLOR8HcWjEXPvr9Po/y14Vay6GNMhFMricQsuaomha2onauOzcGtKMDVInq3vvg5YUZzujUEP1DprL8UOTSVTeskenPZWg4tn5MgqkvWxcPBL1BHXhFs83xZRbPCIlOvX6j9gJI90yxM96KdSRKEtuugexxvOfSmDKeJGw6ZJlbPEGqhY5vD/J'
!db 'oxGBVpbrgTG+8lzSHQPpZS3kv2hPGYx4/1Me/Clt9KJ90L7wJzwHiT7a82y33rWFRuv85LDvz3Psm6iwXCJsFQe76lMyQy79eYvtwaP2ovENZUJ8EnSolbPjtcQnaU2cuU0ZYLCkcTiXjEE5VY96ZWfeMBg022SgI92nLKFjcKyFEpsoJYCkaXB5lbC/+fGMi4QXYApMgAhTGehNgjf3Lq9rrAEuCtfMgEohEkLCp/KxfeXI6b0tRR37KFFXfZrO'
!db 'mA8v3RwMrDMmuGbByKVo4ZlHg5sINfkf3u2GN9rrmyhREzGkmwZWTstI0s0favLFgkvGM/FBWflz/XEZNLyLFt+quJJsKzuN6WpfGtlQ6huuY/TdfB12XU9j2KnWEeINce9y6wYYP670R/rsn1U2YscamPG3RtayHqvBrfSPxc/woYkwSIT+Wt3G3ZtjH94it38k6gmJ261PB+kwQoyweieI4ATOvQ+TUgKPRpIzvD8XIHSCEfDKeW15r/WsluXX'
!db '94e4BpdEvFklZJC80ZmkQ7fY8uLyoZQa0vtDGYdt890f2MdYvix3ZPMRdFpY+HVWN2huMuxgXn0Xeb7tKZ4EYBpFzqQuUQN5vn3a4k3IHQ/VbpTz44+2eGSPmD8cta12h51i+BdiYp/yiFJU3mpp9VbwU16tSyL1gqWWdn8Vba/vHTixjgyTZpFJVhBhK+agXi/TbskKjFrUNdDzqC/O9CAl6Cz6A56i4PuTMTpzsYbb52x0HV6obRk0DTruugxC'
!db 'IafcW2srH1QQQXdy4nt6X2pOcNJtnV6UMEtCXSXPtX9kDefuk6GK+B2pVtU0d/PbOrAHCRtMX+S74xdcbhDYemle0MUJAiwczwqXgqxDl6FRByY7s+2MjdghH32KDTviDOTkQAzG6csZ60xqED6FCIftk9n7AJ10TpNZOviCEatQ47cRY8HsgepqVehhZm/Vi0VKKWY3IZidyZqNyHZQ1mZ8+sWZ3QMMkcLCqLsErNoBOZZnCSv8lntuUiYS7kuY'
!db 'Qa5x6dC6vMlOBljHbIkyt1jOCDb9xJPIspra35YYmt4aT0GBfNTkvd/U0VUvZdYXrAARPbwlZyaDuGDgbw19YzS708zgZWM5lJqYNJ6c4LmI3Q75Auck3j5vONaeih6u8JirloC9drBJru1qnROWEqVzX3CarBa24ulcXvQ00lTV5H/c12scPeqVh94LSKg6LUlNExH8Ir7rCdAMVr9yemSAg+emXEJcvvOutzCWtSN2lzwsOGoIKBz+UjYtyaES'
!db 'DwCCuuJ5WgNjFddGM1dXaU6E0wwwr52b2z+5mwFEhPkesVXWizoZVPBZpCp9v1TyX+nxbL+VyN0FH/TtyHkzlk4t6jjVtOCaxC3FYxA59TTClKShomwNiHS16zzEDB8EmJ1074QHrIXEytvuB/joJxcphThXPRugu218x+jOrRT5FG4evpDbggzhIjI3gzQ0hyLwRhxZ8ngqfekXEiVqE/xrBC2VvWRRDx2n7yaYURDs1m0E3o8mYiPTzTvU07c2'
!db '8eNHk9oQhfTyqmpG2sx/ycATLD1kzdPwZ3kMITjSEPbEnPBnuPacer7wW4+MXqjamhWfqPpw9JlcHalqMX618ngq+NmCNFJhvDI96VLynyufHWpodgwt4LPmHa11PNtzzzwQzcs18bQcODwPI74sqjHmSuNu2HE8hgeF2lNaP6Ht9DkpRas1vzwmaagauZwcTfcu2TfZMh6hMRpZL7eWMivtRTeuMye7odKJUfk0j9xXo0THtbmqWol9z0M0d7Qv'
!db 'j9nXzzFKBJGtZfR2nlIPRmawTxsKqMw76+dLCDStBnledCEvoXNI7xKd9Jvgk6lc1zFCk8qySo+RUTXBvm/oLopZhYHG1NG0PddgVvA0uvHCvlA+curSqYBNRAMO3qcb2eXpp7mbVof6Ua3Q32mlb6JPUVQ42VhawSStRc5O44+9KDDnvcxCCegIQIaKzGpFzso97z+TSpz1eH02YrHROt1dd+I5MxLl2cyal7y/uEg+G8btW7SHv12eJSgube4m'
!db '22bvnLeX/b1j//r1oQdnXFJBOt3Y9okPrC4n2vor78Rv4IYf1EqtstvsnVCEHT0wS/BtRwo9FdW6tAmDMzuwgf4bHbpMrX3Rdxo9CZfvMGBVWfYyjIHNVQLhdnOcetTYW9JOvHwOzvM7GY+FfTg7npjVfrW/U5YhxOirUnSacr7LLSp3t6mKvGu4CyqbiP9Nf3BgwnKaPMEyLExDm/v2CUtre4fbt74f+gwpNpaQcqspASvxppUedmky1wzC+6k7'
!db 'mnvfKG6GZLzymd7/LlnIze04eHPA69FZLfUC2/vn5UniHI6Inifr/iRGNyTuBeBV7ijlHnlbqsi9mnlKsE5r02M3mGLCc/Eaodic0v+xbz6Maqzo07oKEHgjcggcjlZPJm3wvrbcPzoxMkpTttgTGca4cxEYnWkICjBsFkiN6rKBoZATqagtY2vRmlnD01Qgg4wff9CpRBgoCaWcwmrmOsagbCF9mNDILRQ3nt6KeEQW56r8FdY/shyJQOyomVYd'
!db '4c0cBvktfjhajDul93Lw0xMStataoLU5thskbjTyevI4XGezO+LYbnmpxGBQ+9hZzsQvlOr6AoPUAlXdosV0uzCHlBrbY/UKV1o2GUte5a5eEzbtRAousput55RchU5HGKoTDNV2/vaxwkwjqXRhwR3K0YEssuht3YciJduRkgvHy7lebqUt/DuY60nvzUt7wFJe7fDbqAXT6Ql29Q/rGndLHScmqcSVy9iQ5RbiqLvCEmxwARgmvaYhjwfWilpH'
!db 'EJB7FHjDga+aTCrrle0vfRpvvuKrFE2d5jTZ4U5g1y9uguZ+yY2l7bI19KefS21q+Z7a9LRhZuUXDOdqdff00ihtUAsStFkLkzY+hwuUEzr2GR0eDc0rNDcFBgb0FaupUaASdFonLxpPaux3crFnFY/OLCCr/Kp+trvpRWRZzLuzacn7lH1p1Sz1+YPboINLvscCB9OLHVGs8PwTkVW7OfOfZOqTXnNG8cwYn9mzn0HG0RvkWWtpby+OMp24VKp4'
!db 'VkjjQn4GkjEykKM8Hp8fPcnN2w2kFT4PodPy/cztzvLGyyBO8gcvuwZK8HEqJ/THNDXsSK2XeGakXR9R3jo2MY/aJnNYE6A3WZnKVG2Gl0+ytoT7QBeEGKX7XTb9hwxYRaN4AaVNbNp6ktPuYop0cf4YMpumBEcv1x+5PVvgaR8ZnkUMjw415hetCmcq4Gn/dDKfmsXPH9UN2ypgKnUN1ZcaDo0+atOhqTyUnYzexQ0JGmfc5wj11zpb5dr0bWRn'
!db 'hseOwOJAFc0LHfA69pNQ6U6IX4BOouqeHsbnUn/5pFZgUk9VWqd7JJeAAwi30DDkML4jVLv49Fy4bSwrI7bZpfinUYwFUNaP//6EUw/UtlWj2IYhOfOil9bRaKUgPutisbJfKTkTDMRMMIxtXhA84TV3rGdeZJZRe8kvdXOjYBZL0N4sQB+mpPnlEZmuRnBdFwCNcfPeOfaE+vQJF4a+ItE/1Qs1FH07lTYfAodssBXSVV8OsNWImBLjtk6HirLa'
!db 'DryRpZfkbb9OQURQsuGDD7U2Wz38MqwaVDZ7iih2V9fTwvUTSSEmAXFfNbdJcwhV6K0GgD5njvXuTN+3ipYiy/yuwSdPhLCpUzy5UBMhbYofnYvhzp7tGwAVKMytvkZyWV60nefDwgiaHiwBXUfQKTTV3LCY2hevtgdTNK6jfV717hLM+fJZpaqqKrwtELXkPu5Shb5y10ryXUFra8wKwGlmXrXrm+6Yn7zIkmPhuYyioC2WDf8loPP0vdFYuQMC'
!db 'pApdbCUnvN8wwOsLDNkYGQtzdyvwuAvD5URqCB+NEWsN3eOMory8GvGSCcCENuYSnU9FmPESdrJryR2EEhmjozsarj95vj8mRlL9be9o6IKWaI78pqRCWiYiTXpiJ7pmgKUXi4cKjFJ3Yw0NXLsxVsfKbqLpBMhQ+txxvTbPQmW6LO3oES/nhJEoyufFhbDXVLD87UKBM/GnGe9y3VC7g+/Yz1zYJ+CPktNTPBM9ouhreKZnJ5GcQbZRwyfHR7Ee'
!db 'XGnVImsdfgFDxfUk87Q1b1OMFlelQQXyqpWGEe2t36cHGYBbXKQEBvMDyAVwDDByHKBs5XLow5fNDDnMDnMZI2N2+w0Bbvq9XeWrncqXMw/GUtWrhLFcfOpVhZNBR+9UrcM0hkOUfZs79o3eD66psOTpgOsSPWilEnjV12bvSiS5iFLUNh7FxNC1ODCtiNcVhuBT7dDdCZY7DTRalrx4n+Yyds9ktulYZfHZoPzT+oN2vS6b77fh9ok6pVOHlpdK'
!db '4SRY6aPBTit2suH4/XgiOZ4H7mUzGvphJurxdRuRSnWcvznti8x/B9AEf51mOqIaZgYG+AqWOphu9eQXFk6VW/fh4DGMmiTAuMbJVFdFl4vJ8+KXgFX3669vfvztHeLa3nF9Zk83bu4AhUH+zy80qmnYvUU9MU6RXebftsjFCnDF4Eh6SXaMeWOOP5nuIqNZBT1RWKBsalNbTb9z2ZbhnfT7lEQBkbG2L/oQOTn9Lw0D41bX9BY+8yr2MfQ6J8uy'
!db 'a/+FQm1UcaRNDWK5anQSecY/P/Fx3YZoakgeDifFn1ycbuusUpPTcHhWSXreiSCXnGKQDFAIhTtEwXHI3VelqPEpOst6Kju3/+VA+daAzuo7diUjItoRP2bpVKTL2uDm5qYWdwUC4dhvPZmFu0inSaGSJjpjZQjXYIw1ztcs3ijbT2tra5CVXvoRWV6jmqeb+NPZ1iRRcC1O7YPNuQGBdy8GtSN+exL/QKJRdsF0mCYtsxcuKV7QyosLoOZGZ+Ne'
!db 'WwStYmW/JAxz90TuqkkWJsovX1KP2Lq4uNxdVzesAnZdFOFCcrCkxf0Pmm/SIEBe3hkoD1Lsy6Pg8MTsrD54zmSTr3DgUug82HkXbvJp96ntruj/veaUk5QpRBW/CatGKn5FTlUz69fY13elybOmniY88BL3aWiNL4Q1PyUlDHA/yQkNTae4EefY3d1X1dmaTKtyWX15YIiyrx1V0QjyxbcancpHzXCFptWXr3aRyaGJUX2+VJt2rSdOzGENCmjp'
!db 'JGzEWuNpLd+XZovOzpmNsbaDr20tIlUjtzUeggVLjHQQVW71MIdk9BPzFvRU5/WovInl27y3YyOM1JlTDRadRcEtmHP0CoD6a7t/R3PxR5YXZXZdYqfdVrsJU9xB8y5BL8uRQhQ3sfR2RHTYOwAvaxXlr9bJP5K3lb/iC1NUjsbBXEH0Cp8lh1ftQAdjN0+NT/0aEl4nxzfA3ZdjSrLLEHK94SpqERpqrlKlXzfO4gP39V3GHpjE9MQjvzuWE85t'
!db 'C0c12PvYgMONLYsdJVxGtvjqrMtmoi2qSzjBxtKji5KzdMa5KsH9P2ZyLoTmGil9zteiEYTv8TkozFWEAKm5B9yXIy6liM8v4DaC/wz+pyXr0qjlEgyB6f2mAuQsdYgpQPTX5eLnS2F87g1l8GAA0M17+9Ny4UW1suRxK8/CsBr21pvPgWI8YT+YqwRQUjaOvbcSi9vMN5nqNuh6AtU0OxRSKUuq9ZCtU1PViQ9AOl0d57Zads+Npq1Z8j4gwjh+'
!db 'VFc7bHsvmEMiYenZh310VL4/DRI7KvBpNyax+q9GsRm1muphuRnHeYi5hSjaRTs7twbBqd3OWEJaKdt7LI+Hymr3+Dcp27/jyZsINbqIKpSU4aL7bWlOr7y2atxIdERefUG+Ee/V6aSbxpufKpTUl5PhhSTIWeLlhOBDR6yVx7rRXwBf4KFM5fGN6xoRm8tupHEdd3Fdf7mmA6+vHGVk7IYG8hrEFbvqn3a5AT3yx2uUgvEsxeToE1t/3YdB1JXQ'
!db '09vSG2XnLcwvNQ2JEjPtVSxicbjcsFZ8fumpXviN8Q5ooZdRHyBgK2xPaWkpyBC1444+V5iYLajgujzhmgEElgSqqhFJn6/Vj/14Dvm679RlIkknfg7+cu/Q5MIkkE0oMc3Ydzn95E1vb0F8MpayP5H92oO4b3ZjszB6kTXCivoFX29nvyUvhL35zGGz/kMnbbhhI3OVoxPiLKxnTrT3VVNy6SHjnl8EJyYhpCf1dLRoArMMakVA4RMpjQKr937w'
!db 'ApnaZneKvZiolRHYlS6B0lkZz/1bikNrZyZpUo9eFNGtuYKuK/wijOq6rz4ctOnPRHlAjYZoEjibVY2Q2tfPjAxgrZYEJ8oB/lnZdqsoJ6sJ81YilM1sBTzTLDd0saVlwyFj5lvH7vgHe0zR3bFbiuep8O82vhve+jm8Gnhy4XNPayPVnTmoyz6rRoRti6uoxwDFW5nmF9AIC7p8SdCoyX0BelojDtmWDYSggtWRHpyeCtpsy6ew2qU292B26Edq'
!db 'k3UfOBC0EuAR/qvGHjD/0mcVouXLfw+92P92HI8CROctV1xdJ3Ya2dAWvzT6cfWsCW8pic3xRHQjJe9LB56gZGn91j6A5bHAnajhPqsTTAHL45OyYyK+wOZFsbpwiJ1dZ9zRhwaI3YLPKXnhwKR3E/bd1mEHXvxxUXQmqcsYDbOAF2dfZBTSppKa+WAJfgqpz5UTDkCZsuS54PLZl78bFZPMQhbX91Jzuil37Cl0d+Jfsu4cUrYpI3zdR7DRWmsk'
!db 'jG/JeHcszSVZo8C8JyO3+HgfCb1Gz8F5lifzQfp8mB1ifpHSciaYVbRTH8ir9YfL1Jmjq6MTdFa8T9yiveder0zYWheZKjqSO7WolTcYh84ngtnyt09H19HF3iXeoNpzEGhFxsHq/luiW+rHm8lRr4vKT/t8WYbQyKE58VfMtLOAhilAw3m6dUH1WUixiH5/1ZfswU6EWWrhUYBDZBLw0e75x4FiYYfjoXVflzWEuIJV0sJe5v2pRgh07WIF6qxY'
!db '5dPMkvdPaOtbNcK/trf1a2kHlvIv2VaCvcXolnRYSS0qm2lee2uX31SSiaHO80LT8mUbOwOTKb9NVOhB+2hINc1ZI2/xuV/h/YOlEKaOBqYJeLlNRJLn7ngqmu1BRgqam+6Mq0Hz/P29jLfPoj4fiQBCf4N3bs7lmcqP/nQDHe5y+yaAz5e1ZYDZDGUidzv8M7LhiD8QtPQuF+MktxWtUPrJ4lB3LoXpRfvIlIIvSVtd2GDNXcs7T9qXZJjdAiWP'
!db '7URTlYuEqxO7tOoNsJQvyk1JdQHW+gC7nzHC4jw+z4doCAoO9fIEJcqPa9KqsPXNtcczaNcE/43iysaJVohst+VP693DmN2OlHSTr2c7FwX7uHy85pql1FoUgfWAZ+nYFhZ9kqX4dSCR/c6DDHuEGVZge5NHkufGzveNYImwvukYsvlYnb9BNQPlw75ipM6X1zrheK9QaYdVry8TwnIJkkZ2iumOfG2xI9uePVjVSlAl9xlFuuCUMpQRdTh5PQgZ'
!db 'THvcLbNUI3Fk4LWdUFR+8da799PWkh9ezshXDQESCFfVDCwydvNLW7r3/Iu8i5Z7GwnF3qXZLHZl4hv3Hzne+XHd84+f06/rZOkMH/nove4WH7Fa6qxEhu4HSKLSeacvp0EyPtDeHzPoybFwkC1dcIO9dq24F21Lal/oijnd9Bqf87H6Tb/9cFhtOFUZlAbrFcJKnxw1bA9rWH+Tp/zhhWp3GHa0ZJKnxa09f52bB8DX0ckV6Gipssyc9WU+/fsB'
!db 'kdlGF7bBSBCqaJwNM9yX3uYmI1Cfc/E5NuMTIo/sut+oUzWWkQColAI5I0QYf30vGnIiKFhLu/dXJr0TLWTyWTqaeT2q4mYUXjj700myM3DdKVvubsQbiPnmHIm66+qshEReje79jDqmXdWV4+cjHnA6U7OLyRtwbWy8D9b/s3SV2NbAiEHuTJCP72cM9vrJ3ouPFlQdGKLR9SpzduUoyNv0zEWt8donipvn346jSeqZxh5IaQv7emmKJLBac1VP'
!db '2AOUGdZIcVAD20sANUpspCZaFy83SA3VmHACEqea+izEp3kiqQlP0RP7xsTGklsCUqIU7bFy3W+OFsrcLXa2Rcq51gjc7hcRBxMztOWO4Lw0wIyLV87njj6LUtX0ZdcoHowwrtcezvhGyc9wM2ajrA9TY4WV3ujsSgJs3z4W2Ui5Pa8TIAhrPRB49en5K3qCzpazIKmPOo0g2B1pISbHw8Xqan2PgN2lwtpLfO+Jg5itsgk4LpkRSp9u5fYki5e4'
!db 'k/t3AF7bR4k0K9puB1UyQZQGm1iFAI6lsH5QHP2kj5jd4RoXlE/jwdOw08oy1xDuM9UqfxmtKeRXYZkARBoGwG8d5k4a9+Cur1EkC5luitPtBfNn6XUbjEuB9WF9NQo1W8fpAKHaUBNXaOOTlSOL7Ebq8h7aC7SCFqTTcC8xGV2wk/V0QfQR/Ju1xLQU/30W9lAPm/yu0Ytj/t2V1nOqiiOMfocNSfWhGvXBEsGbqhF3Pf2L0UEvrclL+L056Rpk'
!db 'BaYSOPW2K+R7TaLPPzjXKxcOvN1eOCO+mPys2lGNvLkSjI6cH9+bT9tLSkpCNpqb6M+7Hx7CsIemTNQHB7rmT1HJ1WH49ra5GNG8v5OiVw4fS66Phtseg7gTsKa+EqpPPMKQf7i/nJtvdD9rLruzABDRAPBHCABFQVz54WcXG5g32bwt8hwCdmJuz29D222ci6oFhhJ7QL+GyE8JvD0/Y/wGEsrieTv0iG95Mrbgl5fVghvOg89AR6K1e7/s6/uw'
!db 'eWJhyst9hltpOche6vzTavBktsJQQlGNeHNM7WTdS2j67rVAaR4UbfenZFs/MfJ7QRii2m7Y2Q3RtVliiXvJmQgvI9HhGxgLvzpwQ4zittqLnnZp3JCYwlvtWhbesQmV+xTPfsfD0YFMFKVlOGawOAoEenFgQUsH7YuLy2ULeE3OEy/Y1hC/ETHp1n9Lpn+37Z/CZ97md5NQoVLCoCVT1NXVFYbZfDAia3lfC/D281Q1COriEm4raHF/wXSqcrPP'
!db '8A49mP5kb5XCc64pQItbqzR4daI523qYBpz++Ork2gNwemnJP3MLkbrmE3Zrk+JsU3IxK8cg+eYqu4mMSnIx9YL7kjMFHPbhhDiYg7kfhBsufKYx/M0+bUqCWbmAiFg9qx26V+bStq0uUGjUrsIVyrxT+o8chJXCPxzW0YgwyN9uvJQKiJT5Zw58+3l1ArPK8Uz7wB528Fd8nNVZDc1loPGXNfE5XoIzGnssxZdOdMtt+/pAVfAllOZtx/MS6I9l'
!db '6g4ODmohK5G2n6h4jKgPdstyVBKtrK1xrIgLlr/Uy9yc3x/0J0MOahO5FZf01zgscZhmG75dVMzIth4LbXkEnqegUVLBOcVrt/YiOmudDjZSkJxtuFpbvtKbLo3y7T3z2F/mTZKeDGAgjYCaEKtrWvfB6UfmqbheP81ztRySujhayDbMuy2dnX2pMvFe2HFapIAVPVFurck4qn3loRv3aXmCLLNN/i3kqP7b6aoyiaXf3CkrLiZ2K91Vvg9BESK3'
!db '2ML5LCbB9oWGyehgCJP8iCim4BWu51tIWvH9yYb9jgv1vCEVhBTnpP8Rw/+PkDOUwBai1dEARcLwkEhvcXBA12j54kyM9+GMXDSnwxqQYCFNP7isko8vMuk63ZStsuT7nTuWS+hDO5g1oFnlxTZpkirCrqsPenSCHYZi48kdiHkhlPH2PtDnjBfHlPoINI35YoN7C8PXvOpkX+w+t/hbq32P7ezOxsu+AEkhCkrKbVHmdR6S+kgjPYrSu18GYeTG'
!db 'ALbOeu/9Pxi0ynvuSz0JKgZu8/AOAbXC6VbGvzzzqKH4J0HWslENGvwMaaej5YQqHf3uXFJ99t01bMquFksrpN9bdpS25DwCf/7dF8dnsulLc5acRV1gtJtSlzIgEkjt7/K/pV+dYKvGt3sebom4JO9t6BZfLlpZziBlsx5H3QzpnHSHyJnL6cR3Dhhx7nSOskf1VUe9CXFvNKSFRfaBBJhfX7JGU2CK9uGQ5ojxNjGg7AdiNM9hNYH5B7flKfae'
!db 'nolfZSPui4VCM7TXbqaDCwr3qly6yXv9/AJk/6YI+8YdRXgolS93PUjnbuilvDxtUNniFv4iTgpwGaMmefwr3/EA30tW5KRn3xc8eJnqn+DKKrrWxIPv/hcGNX/YD7R+/ItuquU3bkIo/jVuVqDxjXdlLlE/02stY0dKpw2ZAfrYZVOW/y39Orp8p66D1tN3c9/fmEH3gMN5qGb7MVRdOvby+ahHMskv6wZgM7yvidFVow2YbkzK7EStuFE50mgO'
!db 'L77flY/1CFO1VQ8yc+x1LoFUXCQvzJMoaX7hmw52KDJnyZscq4L9McfZkQpRBq/4XBokbrFfaRn4yZl+/DJAE903LHm5AW+PXqrHWzKy9niC2xYkCTp5x/K8hEfmatacWNYRTxl0v+sMrZIc47PmDeVKwOyKpaWStslxeKtHCq1stB+LTwyNEJZV0rT6LloVQgSlynAI+cntpbBpjxltGIQYLp1rxtWXDWX4cjc3mO7fayw9Xip+4OCDCrPrahIO'
!db '+jH9B7u8Wqu4mV0BZKmrHupZzD85/lv8TZy62d1sUOG4jywRc1uOB6EcpwM89HuE+oz7hLI57CTg9VNVM3bDZfWvZod8ZihwnOPVQsm+Lpfo96w82ehCN+14xrTUrU22HaIRtMJ1Vud+UluZ77qbaEhcb92dFJ/e+NbcRr4VdZH3q8M3F9ng/nAOcAj3XUledmwfPbsgVMeT6zi88JooKfec7Zr+9iM6Oma7RPpRC+tMZSBpb2mPfQ1e/D12KwD3'
!db 'j9EpIL23KTZls79YZmCAohQcA7RaM+r6Ia4vdf4xMJ1aTKw1583PGH5Bnobt5QaWiTUdLiYpdejM0z96DRLGuZCgF2Pn6b/FXWhKrz0DM01ps70KXQeJN8+6xq2mwiY8x1nyMUQ1O5sanMZuK52C94Mgh1aL+ghQ2Kv1jwsNGgnQqLhQjb0BJu56mFV768xXw/D7J2Ad90Csy86XnYkIifgvyFnNJtGqZKLUzPmIUaLK2fX1TbsZoWxXuSyBMtfY'
!db 'iNGe8tHZWs/3o+kPLdgTCDpT+FmlPvHKPKBK1ylqQ1zf/0hga5jQDDLCYgtn85a6wapkwucsj8keDATTW/2FLK2JhUEhVbN4goXQBLpI6+hMtqx3ly7Z1iW8+wZj30pI1DV3nYWLKc0/NEzTweck6es4zoiZZXI2EMJxTpEOVs0sj3GYBC1tNvFlIqdzUjt6UX9ZfoWlN6T4Foziy3HjZj499N22RcS7tSOShipX69l6691ibjLfFYLRtL0JAcbS'
!db '19ZYk8No1VM5qJhX7lvr2J9A+9IckUBgjwHLiWQ4qHmWGnSMqZwutGGwZa76E0YL9hU49aX3I5eiTjNQCiZCEV0OW9ZSDkpq1azqGuvSqAS4WP6pQleutYv+PZPkskqPxhPv1XRr422sSA8SDGxF0zesd/sGTxzmzpljpC1uUZ7ZHCJTG3W1+t9B7HVol5VIx8TqXtj1xwiK8/AM+zZ0d8fyoIiN0Zd8VQ1TH5Q9JIKViHwoM5o5lk8X7JtIxbzz'
!db 'C4cGfUf+TonuMV+U8AyRk19uBrgmjaREdlzWzFRKlsSUKyd0H1ewYJvskO7KqaKPw8ej7vpQmvwFDIUJBopgZE+LjsbzmThKz5sqAcL4Ekzzk4cY9FosWWzgxvLTm6I0wn/Ra+ltb8Anm4kqFWlaA2NGdALsQu/R64NMJDBfxKk3eJQX+OMe4PrJFkfVVb2IqtGPrCA3o7N31j7UxVOenMNiea4RUx8we+73ymn2DLx251MEdXHO2H2/zUOmC+0k'
!db 't7tD0Ilb82K2RDZte9qXKuq3Me96tt1KyumMQMXnPTzwQStiW2ZMpvVuPaCs9yT7UDSoKpEQl4//xKPgJRteqwJUWx1moNjIdGNUNcsbNqXDd19Ets3uVVtKlImHAU0+ZmL+wZleAQVWgDX0AtJY/JcTlTNzBsfvlkv1SHSXjluJ8vYVNo8RWQpXcrsdtYZ83P2eiBQCfWXP6C2ZROph2eYKV8QpbvfGFjP26rXt92gcb5qFsO7fn6HwLyD70R8K'
!db 'zxVydQ/Q36JcL6vkdYuzUHOz7nBreODonuTfGeytP2Hsa+g4cvKttXbe652VUFSCBm91nxhzC9NCq+Ujv4yqz3cAZmLbdmq34bYZ1vrxO/oOJaRTjSiQzCtVh142bCeVMdU23hfQPYBJA9Z1vFZ8j2ZmKOXSA5T80ukOu4mQGWWaeep/JslodmObffkTMtGsi5eAnZeN5g5HpUBXiSq7rOierb+qpHe3SXsYGckjLTtGl+gK1Jh/kTzrlNubdGVF'
!db 'qUo8bMHHNsx1LJexHy0t1g5j/bHomOmbVxxKWyHuAroW9zhqHPsX2kMT8QUkl7c0lYi3MKKNStNt74WFg4YdKPTVT19M+h213HWcT723KVoIlO1eha4839+9odYuJZL+Kmb/qIyC077qHfOxE1LEjC75L2hZRZeYCbuR6QexF6DlkRHsGlr6G0nazzQKNPBOiOQYc6xrGBOm0/XXRdrketiPfWBOFfceVN7V/trB2r7W6BwIJfiT/2JcCQg6n1n4'
!db 'iW2U7IobuxLO+dR4v/FL2XLuwcDUD86deGWWLLuLoR+8WB4PaTKUbkcTPFET+eDc/DIXvS7X0U3OB4mRO1s/id/UoGkpV/Cr46KR2g05CFrInaoJAcl+JChgfzGzxA2FIaWOvOqR2FOIHX8s8S15h+3o2n9CSo7fy9tsq/X0SOk/Q+SHnSuIhG13fbNYcXX8icVPbfjFcz8pyVnG418pnb1Ozc3Pvi2BQ0VLs01MiPe3p4FPjKdYfcX+VDdHvstf'
!db 'wacEpl1CV2Fz1nrXYct7DQeWLtazPPDatwz8LD2TR40lxZMm+q/0DN5WGBWkCenbx5nafkJ3moYvoh9HcvP2ckSFhNSK9zUgWnbXN8TBjL8yWpPmcTnOsBS+pdebXXeb72Q+dICX6mXAVDS3kA8XNNGNIX9rnsFTR1kAbg4sY3U0UD/7mBhvj0gDSTNd0jZ8eo6+qdfwta/o1sHSV82taEPfmgXPv8mVjyh/6KKFzRQrym5fMeUfPfZio/anwvbH'
!db '5WVTEVQh4JgJG6sWw918t+j0DN4ijG5DU99fdMsKWHm4HLQjFLnxml8fQLWGeKwQCrGHaKtpBv0x39/AazjNlbu3ZQR4VvJ3IVJVUyh6n35mpMUfaWKCYbh8rl5nF4yvyKnobzARadC0e/TUrjVXbDGuBFnm7rQWVZwQC/nFJVpbS9uyKdIulKv0568hrj2Pe/jf+Qo/zY635t/FxAT2MOpnK00BhNn10dHywyMjWzhc0SWMlw8Pkg0yYlf+mxL2'
!db 'aOzBqe1XO++ANgdOVIM3Mjvb/Oqiuylkkkg9FuJospI/L/kHtLh1+kH+RCemFa/HClgkMT6FmIhMPl1Vo6GaqbnR6sDXt49d0nTlVD79hrLIWFz98nKCjkERzp8Gyu3k5++J7t6hZx8JhjcU5ZDJhxZANl93yeFurN1fWXqWwNr2D9pM+ohAiV79GsTs5PMI1Jftb+7CWX5/ZbgA7U28np8LpynXRvleet+h9/+XSuS/JFBBUt2+mVBOuGdeeXZ2'
!db 'djlEl1A9OCpK42UNzPczQnalL1XY98eZFvfB9ARkpTdjDPCWxSCCIdswoq+54vJHtoVvJPmrGeWuC1VOHIgufI5v7wimZ1XkNBRVxr3UbzHJNzP4YAVkact1KLsZZ2Qj+PvSN6TO3Pq6BAXEV3oypBMC2rhMhH8ZeIFJ7BwccKQprxw63VFB9eSy+4oCdbvONL2eruY/NLwTwSK+UzE+rlXcFpEqbMk42rA1UC6tGAp3zLH0/RKvWNmNI/0Fi5ZI'
!db 'eDZFsUQbLqiyV22RhNWo8mcD8452bjywOqDsXPmvPI/4/3haYVE5MiqxO733bSWBV9DHkSqreeFiYCDz49B3+XqxM/zJc3yfgzDPGQC+fHlA0v5WsZ3Vbb5s1LSdK4XrymQUvB5+0rOS+Fk9Vscd80p0C3UMSvxQ8/lKgbsrep7ReDZH90gbv7txVfrXLuNR5WbJA48+bq/5Wiq023IY/AY8G9/HOw5uz5MsfVRSuEVQuBUyp88Nnjyvvxx8+ML8'
!db 'SLBYgu/IZzcbe06Pf7Y1p18GyD3fSZTuuI3dfzoxGXG5BJMGEWxfB988XQeJ6iEvxlRnDtt+DjMe0olgpEl0K6fTY+vPaiVEi/l8vsSzBypSFXe/jost/X50HJi2/sRYeoynFyhszM7zUz2tseIpbhuZmGibHIrA70vrB9rcxeW7H4JNToqXIKSI0GbQt0ewjW5dPvPewRGPrdl9hx/Pjz56qbQ98bg1OsjK4xZoEtQ7e+emK4hGYV0BZtcVoULV'
!db 'V4mtd7QB1T7BfpyA5ApWV04XSUJ1etNS0iRc28LD5ctBN8V5gGgcB4brwlaLGs83GaNu4XcTYPXtNosLh0qwBxC5tsGcUgiipNeusMRxGOjwOEZxItkgxJrnWBwlYuvSdySa75wPSViydElvHKSuUebUuK3/oeZECba8WcIqUf1MpgFta7P2bRxcU+ec4qDQ9i1ZFo/35HJ8XpopQRp7mMykgSaPcKUCGR/Q5zl2PzPuGa6/rvmmAnxIi98b9AKy'
!db 'vr6yV1Rf7k9lHpNb1dGbIsOpcU0nIDg9Iz2abuoRjZ0dL0H0Ry5Sq26TslUFua8bJ0sqZpiDDuhgruDYKHztOKDleD+3ha0L8pXM2p0MUG5KpvtNYp7HlVtDYj9QZK+NtlFw9js54T4c9qiE+zHCY5stj/jyvfAJQvnHZ8cKEzHoggXQAXKZ3LbEkZzZm1bvzjYNbAYFfaa06ql1Ocl6KJOsobi6OYC50ehjHsxJvDd9Yqh9OmfyrbRx5TBjPAOQ'
!db 'MIrZHkTEOzs60OwVcSxsDG0URgn50DkKbgyCDBInZzQsnvlwvQD5ZcX3qFeZL6xh5D1UBPb2wu3Uf2TD+7V8lVzNA70eqGtyXwSaX+4Hv8YutD5oem15yYgS8dpdQAHtp+2/zU9P3g3XSyBYr/N2DfI+1IBvIBG6l2HZDjpRAWTkxfY+pQpshimPmGPeSryGGcGduEnLy8GjFq6VGWh7HBupD8rN7NHZo0qisGeytptZrENWFlY991kezwSqaI4G'
!db 'Ld13T945axi4nAU1Q2g0wtr0+sSgZp2Mjbvs89WNI/U3qYFtPZ6nF1uzG5hfI5hU65LzfEvl6cPhWXH8p3zDjJJPFl3GQJeawsz1lh51aE9TvHCk58XF9nY9sc8k6aYYeJeXIVLtbqfOV09DD6anjqOnHRro+iqpNKsIQMIJSqreY2adrEnL9yvrs61gp/NWGtM1A/OeW6fFN47V8C++mrRYBYeH8+rztKmbH5omZxgaoUHclZ1rs37djFwUTTUE'
!db 'iXrwa18Alu8677n6fhsGF7EzAe1JqabWE6jUVepqdrSc5492BaxbkgWwPtk5F5tpJSF2+QnDO0G2k40WP47u3MWyhFwhCN+u59RKtSMGaLweh79UtTG/zD3jGkQZy0i6O2QGcvH2ORUCQs26XmqkMzlWP3O2aeoOpG7Gz4xn/8NDwtEOpPEyRUJwVCTZ0a7RlV2hoeIDiJmgvE09IgOeiYRrjrifn2x9SRCNzNGzs53uL+zvJPt+j11X2JJrve6R'
!db 'oy/mZiOptANYtfosHrNT0P/ykQwrO5tLhbfb9uoUK9nwIbHzRhW6Ti4sP9YSH+6WvdFrzZJH4PjJ2fF8Qr63WM0hmM/rGi62q0qaQ7EMoRGCCL2fELv7zCaGzYyWxOVtbW2samNAjTzbb7O7Bjoqk0zJmcstJPV3iiWu33WWdVUJ3uCX8XZrxGP9ghtOuXOeRBCqDEGOATHhLbP93K0th/MV/BTe3pAQtfQpiLlj1j2IEdqk7iShis5nYT5a+AJO'
!db 'e6ZqpbAeA+p9vdez2TBmjd2WgCil1Y6D4itAPEB+bljIeOO+CPRXyhDd6fqKjr70dp1wLnqHdkRxNk/oxO5IJ7LR6xOUSqTuFDZCNN8IsXUwxi3Xo+svxmxLT2GntOjez/HsSScmZyfPT0tIghkvwGp93oAGjVRQaG1+Psnl5eYMiQvZSrrwScaP8VGTrpjLn21Nvh/Db7CQOgcbvCT4WPEzjuWZ8R6aYIaNfU3FEVX/vmJlEYOGL75R98TOOPbN'
!db '3BJBwpo4DH4CwCi1BCHawV8utBesmuIhP9T/GE/4an+mIZTABYhZkn63LcBMy9L15gFzlOL++eYzu57wc1igNTz52AbuwebCXalt2m/tPTy6OlSq4jgDlPebGBxfhhyjp5UYKunw4/iTtQvX9g/uEt+UXcG6S6R8aHnmIKT103+twEt7WbL6vVgBMvLSutnF/IeksPwtwe/e5UuvlvNiY5rQwl/1Un7Vow/rgsHM7fP7rsYHUNLgnpbSI4mZ6sDQ'
!db '15kD7OV3OROXiQ6MEJjSAwL/l8E6i6+9envD9Nsm7bYpbLOYFXnwpTsgnZARxF7WbGzGMNEONEOGy+KkFZzAxZvd0sBpwrDmMM+owuhvGEn1nuf03ZDP3h/AMWqGJ2OU4Y2RsoV6bJ6K3rNftyWDAhVPvHzkI3k4DNz0B95Qrg0r7c2JQ9vluNvff4q+f+cuW24HGRm+3EqXjvZjJ+an7htNgGRQhya7dcEa2LW+sCdAa2rZj4M/73u/0/cNnbzX'
!db 'tyj0TPKfLElsCzYKi5CZ77YGKbXP0zYPslvCa581Hsumb8g6CDg+Dxmlb5s3158otqdhXE5hOD1GcpJj8F9hQFJzCgzfKyuDvx4oWVcllIj4lpXF5yiYQpM0u3b9cjTQdRqRw4jX2Hr5jeLl1Bv4q8MFx1Ip/RCLt+5J26vtiOIAHmHVEEtN/gzb0FeaXVnC4K3Jl2+esgLgIihasQxLTYL3tP7vAQITN19/aitXXfDY1rxx62MScxYsGyGlLywU'
!db 'SbaLDXAlPAQOr2/YU9QdPeU8iJKy/twVthYFI5mbzfrgddKFuhu/0s3bx7dzXrx7GPya/Hx1jGQgkXPNJON8bbikQ547LG4rPcNHicRbXtoDm8EG8y2ozkgTtm+JGGzDLtluYomrxMvLIEr5lHWrTyuNcprgxSXpZrqSw2Cv/rfx1beErULKtQt3P9r1DzV7EzdoQZnPS6t6q6snxMtfOvGqCca8AJEIjkx1iPByF4uMBwqu6Wraf+5teVdCxD5V'
!db 'k/j50asGvhzIz5UChx/VDM5q1qMrFsmEstbkObn5ZV4NUuHHzJRlXHoOJBy0f6BHO5WQeJkJC9+fU9WuNxxQdAzdNV0wQulqFqmlWrOcsuIfHuxB6A4d+z5GlEFcPytgee73r7k+IEkqS1uJNPrmzrf5ygFRh4jkQVfx24oSH9UPz6BZziUCzEwppRXzs4oCPPe6GYlrvKbLNQwnJNyI2ni+pzHQfVpJyOd/nPCH+NFd5WxkyceM2AT1AC5/MBvx'
!db 'Q/+YdxZEHPuUuS7Ep0auR3vMDWvdBqKeENPVcNZkw/jZPleyH9EAukVPPQfOVxE36h0yptn8ZbnDjL938GQ37nFH24AyZGyWk38a9yGK/Um+l9ptzMqIj2V8GN5bk7/xaLVsUKBHpczgluvaYA7Bg7jy5uPKG5V0VF7G6/P8eXgBtqZs0oqfslR5/FOEJRb3wPXYQfKQTZpw4DtXjx3ST7WWncZem3SbnismnMIIAYAJly9Wfh4kIEYicapOdolW'
!db 'CIbsWSiPfV4GMPTkKhZ/IpToJXTtJazMHSjWsGBqn0eKululFpwhJ5akV1JFSwr3LCyBrdKjajMUd5dvV8bcPeEqPxQVkMQKfyKs22Tn3GKX9si9X8nlcy5lCxGz4yQZGfzkSwz8bohVGBLbMKGiSNa/1R3AIV3ojrl3vzF06Qd4P8q3rI3FZeKR4U278QNHtHhGWtHporAi/LznyKvedQb7VhKKp8jdfj2BxUPjsnT0G1df2SeX9lvz+Oe7dChI'
!db 'QWow7JcEMDYmNiOlZKIUIvcTRFSWj6mX45ay/SE81RSCFn2sn16/rJxTqN7h/QtuSvhgosN5yUwai/5jbPy510NZH7cHI5pAaPGUh4OshmRjWN1GYSGSyceyf2zr4BMgI8npXKKXTjTrF0r6nq3XjupowoTzhGlj5fdZe+i8ennSh6hyKj9a/4GeEVZbg7Nnt9wcgMYNImbvZVNBw7dAyh0Hn7MjlkJNfYrY3WbSvTMeAVb9mivWusNU7tK6LgPY'
!db 'AQF8qLyxW74K3O34JmHl+bmjYzFN3re/bhQCmumhY9VEuZrYD+rJY+OLB/frDgk4J++ul4XxjKnWdTsvkaZ+mCVOuj+qe070Kpbo68qG6RALAXkwCbZndEUR7bRC7WBw1tQ+kXoX17BBytL8b78iN36Wj1eUTnO5GJhauVhlR4azVhuEGkaSzC7z8LoKqlXlFX6qD5sM4HmoalvwJ31du/aGjv+3Rnft3dtHfyp814Ip/0tFeuOnmeRgUUuLlmcM'
!db 'VEzg3iJ8BxtHUbVcM5q4gCRCGWZgo4+30+OqElPzR8tNVSrWvnAveptnnDIY62Gwqn9vtCGcWdF+La1Ys6vc6O4aXvqVtTnXw83tIlYlU3tPFp+oK3Pxzs1UMxqpmIcyAISRaSy5n0Jdb+yflTG33vuccHMiQ6urnE5XTLFYVPvucBl56KP0TMhiMHe65NmbrVdmOt0dJr5OkJ3chfpL3sNet/4PAwNa2xGxpSS//xnWNeeXgqD0fvmkV0a3WF0e'
!db '/BmRlkdFVKiIrvYAHpJr1/q/tdJ+4LnyWBU9Kpl3qGrctPnCe+twzE/6bD7CpHvyi/LTtyxr9kgXP4WY3qp2534y7uno45YQsmrAe/qv1g5TIMobMuY0z2JcqoBiMsxK1lM5ZH8zmtEyOTk5NpU2fESbblj+T5Bbt858Lp+r+j8hB9dKbD6Slal6xgvSMjb2UfWvqnhWXaG6+zPzYes9lryHyISHMswEOI/3JBd3WWyfpeSPzrVUUNPAf8lAwGBK'
!db 'HiPqocytrS16evpPEModMxqXD9AV126r8lazEBs+Wzu7jfV12ZXbeyQ8PxPukD6LwVVqQZLYi6BQElO0D6lY+no3lJUiICDMnAa+uvfhmx8w2Ggr5HD1wQMynnd4E9puzrWYgUo+Io8TcvloGQLNuzJ+d8rsCH5X9JwbJccQxZVyt6C2VvRL68++vigJxj4fTbeOSvBSZ9ItSyaBx/Lh7dtmIUdxD8iRbO4XxyvmhuH++CTqNZT3FxmNPnJTsLxl'
!db 'kQl99JOBJx3IGeMSOU5q0+WezfO7c55XfPz9wOXatReED8j/b4tIswFbUyfrXwJtg9r3wlk1bHp1dgWQEwcZMOnDex5NeqMWvIIbiQajVoT1zve48VMvdidQIiFpjyCHo6ERVvSpwZEZx1EQax8oIiG12ELHoFW6dIJk9QOPiKrcda25PpQ3X9iI/c9phDlFvCtCo8FNEuNbj5TVILmVeLxpX3A0Ic7DlNi/FGgDOF/u4o1DuzvHR5++YS5rjPua'
!db 'H5gXeFrjPYXomXoCf0xoMAN0/Q48r1qLL5dNpP1ieTkXmh0E9XUJPzXo+pJuba93o5SDTn8/ldQ4qwe5GhIaVU0ItE2qKqVxiW/4ZXyYtdUzUp1QoVfWUWEVlVpphoZMLAOn4HnjgcqUqf3N/PrJsNGkJ4AQNRGzPksdC81m795HUftZ5b79AjFZGsn28eSWnglcAjCuQrO6VElm9ZWA9ZPjnLU7ZmTBH7RTq18ng55Frcgrx/b+5KnuOHRdqkW8'
!db 'f2aoZdzL0ySp/r9Ke+uANptvXbQKLdrSAsVLcUlocae4uxUJFHd3/2igFChQLEBxd4cAwQoUDW7B3d2CB076fb+zzz737LvvvvvwV2aSN++s9c6sWc8zzyI7bpOpvNmMHwpcw7GCgJwKsYv7FTc/991WQ6OHDmBznXetSvsCCI1dp0vv6RBOP4iUg35dXsZGWPfEDItrErX3tATfrMF7QI4DKb7GHST1LxciNfeDjYTS5xPnB2x7cyRJj26ZPMub'
!db '0/f8bjehp4HnWpnyeCMmE5OGDRcF87EdJ1kgOolU950KTUreEr+TO5yOx3SZxTPlZ7NDU5fk2IZeoUo26wsudmmndpSgQu4fLC4hbDWGsM/35cz7G6BcPlNTxdaNcKUo1NZCXxWFFpdq0XBwCKMjoZmfV/WH0thILY0KU75uiWmpXexZfSp/v1ok2Z0NG3nlZgETOqUQvtLdKbJWr0YizurgGeynZnDWXJ5DXr9Znf2tojou2l15plckcd8Ya6+I'
!db 'Jq4j1iUzORqSX7ilp5wSxY+B19ejXnKlUncn0WAOFrjZcOJTgwkoDB1cSi/WGKRtMzmm4+OV1oUMtREaF7VgP6C+ukGG71onVzDQukgUg46eT4Ju1oDVmaKgprnZ4ULn4FWylGGt+2HpLT0tuMjf5+LSI+UtP2ouF9kSpV/cMCtHODude2pU5HTov+341Sj5rrACp2hxYUbXa1LJVAKDTqzkp0jJaAuodLZBfffddFDw+XV4PJXGrkEpM0umXcnk'
!db 'hUMRr8lia/mFg4ejx7to0dCHxXRgt+5XMA7Cs5GD+ZvuyClCB7vGGTkQ1UJfhuPvNHCeJ55cvEWvwc3cIIVen1xCYtZtLLwuDgI5mPuB0HcpKq3OVd8CBJE41aqaTHhVWWN9F/H8nq7+SSHKjgleFG/o5o8sHO4E+4DXeyMOb8uVwduvxsaXb8+K+TPln45pqynM1sVR3MSjfk9XAim58q3u2c6HL/wwxjiKLS4RRvaWzR8tFm8e748nlHgDpoyK'
!db 'TQF2AXb5x4ldRjefA3p+WhheofIVh1DLNwJwS82afMdEca1WKwEVTSH+62MOCTg98HZyXcmuJsFuWqmzLcfrhkhdVCqp+Vjvjgn7xcMOdl1U/4WVsoUiku0LgMfzNzQBSfimLkNgY44oOZr2NXvfuDWGEM/twwTtLcWgpDekef7pyoVKCnKU93dqXfPlKmrOMcNm4ERZdSZsl6oUCkXhcouNANwnE91l9eWwmuxTU5hCJvzRRVDAXzCQvZ1UjILw'
!db '3XDsT1C4maWs/y7wqfZhfKvDXi7nGJENRrT+llpHM4QpFnenBnpNurO9ZDE+3vi1x3zthEkwBIg3N1GltAvjJziKWjTAoqzspXoBs30f/8lcRTxtJFC0TvnvAZLnCaOT0PS4Eopkus20JFEMQsQnDM0f2Yc7jpfNW+0M7vpR5cX2pipOQSC9Shy5hMqPZW+GMupbPpLwq831xV6m+VNNoS84ewwEi4Vc18cyJeBu17gDwVjn54WFHvjR87/NVPjE'
!db 'iPGy2nVZ4Rlz2iGPH6+SaBx9U3zck7HRxNi98pjJcUaZwjmN39X2tnq90yO8ueXmOvV6Tz9XjgJWRK13SE7hDOUhIFQUefGM0eb4evNsN706MqDsZqDagvysAWzZMQTXNo1PcAQf89lEuvoh99iisEGfEsvsif1mLQN2J0IEzlu2C7zMbvkK6vp63CP2kG3xNRJdqRZSHpH3MfuWwajs+eTzRTuVRFCpNqiU2K4ra33mKMXTK3rEvcOhscfaz21g'
!db '+TFXiMf98o2FgX9/hQlXpv3qiPUuHnoZhJcnEpw3bIfYl+m0Hp1cDN7Gum0EkJqHUIvbfLKu4vHfdQ9GNppKO60KBltZVaxyRU65aChwFMQ9lQ1lzx1Ofjbyk5coveWv0UaiLZllm0MqSqziHuFyB43UAo3lXtORJF4iwwRw2ZNDDj7hVt4CWkztEWyi4S8pJycR5+Y+2qdmDBicxBHCAqrrC9nFB9pxkJaMeSQoixNgpa/JXdfItUQpIK1MPt07'
!db '7zk6z+jaS21t3fAd5Nmw2/j48czw1TzwIuKM1g4WaI3H44pDkTvApoebK4Wc7wpsKK2tutZXR3ph2k3XAkNLsKdG5jlGkchDFv1ewtkqJzI5nOvbh7CdUSKLvvZunf5xq03k93pv3VDI6jchi05OsJySglJcofmdx2d3BX4iQ3bcAt+Wu+XlCtPCxW72gqueDAnL0cpLz0iOBHLX0PtosnAHxatwfK20HH42dsaX23XVVovSAu52/pet9xNQzd+p'
!db 'Xr2g5u6NvMkHwaYqb6Zlm9QIT8ZxUm8UPN6+OD9ggIhGmLMOmzmSaJhYHEuf/R75liAuevuZZDwk4mYB6nf/3Q50JPTZwnDaZynZzyGdU9NWXFpYdYvq2Zmhmw3CtG/NqNsYCIbx77WQpoTSnJMTxuL0zY4u2xTaDLKM2NTAgxfE6jFT7IDpkSDnUzCf02pynQAyrri/a5pPiSuVD+HadTrciP/0dYIO3eosMHq61erCf0boPBAkF+8rqKthuF/W'
!db 'jf1mNXTfuNjmJcIk6uYXsKQ+za+m37Dmdo9liKLYmYqGh462ydUGZWIbNWUH89wwKzbCZGc5FrhZoNLV1LPctKkzqGy8HuCKDIsbXPSvSH9Np6HGHiuCX91TM57R3F4ULSJWDe1F7mU7zM9lhL0Pmb9BW6A2u7Bh66LmbpSnFhyiLQkEpBZMyRjOH70BckUX/iioC/Ems80ZSmDBdsRmFu45o4Wz50+6IWNiqXyU03JjzZKqfBcOlpf9M+UxOaL9'
!db 'AlQHHyfXaub7zOpaBwFx5simvTSqoHHC9QsNt664pebEfRSA8SsvwiStHCJBy/dvDBZqBT9O/mAYscE7PJANqGHwo7hGduJ2sKvv8FGlbroHHgv7cAkBlZsjfISVvoazqX4GJChpj6ifurTo6IlZ2FxOpp7KMHGlHXqkdlPkN+wvWKi0QPghwiDH0bBDU+bjF3FTlTjMgDaJ+9lZmzKP4dg2nD5VBwa/MoWkcBy0OVUyFtxkOzuWrOAYs23XDTrv'
!db 'xavr6GXhv405/ajaC2VwnbhfsnKQxCBkcJ7immzSPKsrw2Np9L1r1cGYmBbjyi8utEyCOSa1VXhLdwYtTt13HlyvuCE7CQXe931ses/KoqbdUOBtS/wGHdaake52qvS96N3xkU1DKk/RdsBOFYsOBhKfy3cXqNMYRsp21sD2Fvxz1jxN1CuFWNkLmMYf4CJVZJZEd59kcXLE/6X+VwztvOH97+veUJgyHrnX+YPkbIuxqEWU6kPVwOFgsE/HvPLB'
!db '+d78oe7lzPrl3pqA4XG1h75vueIL/DLMnmQoR66ubmcU+1IZ/1KZgYn3U4rLleeG8BD3AyGVhsPceV9lIZro7dIRHvlLg+S3z4sX56J9PaW3l4OCgpJPvyd7JC3wn9EvpAJI9e9ntdNmT0+wJykcNL+3dG5Mfdtjo2tqj2Hy3eTqlkwWpbOpZ2HBZqrm5DF8nPO2T18NZv3N8r3rxGs/KS1me+HQsK9m4jZpC4lxrbxeo7Ny/NWVv3/dwVvnwidK'
!db 'Y9aVrMSISfN6O4QWz6jixQfOjRA54ZGMaItwGq1+76+kf36qumxPonVQeiklFX8L13xst/l4P3PRdNLXryqZ2Vq/1KSDP/ATSUmuMtDifr37yHi76gDvUBUwDWVh8wPJwobNvjaaVbTcgpi5VS4f205fuGg27i4nc9RI7rrKBwFZFIh5GHt4fPRYwIvelaHrShQmcHTG0pg1kBGjhrRlDxkwSdALW1Fryv6AV2HLaDdguHAHiRls+iQdTkUAS3xP'
!db '02x7fesRaQV85LRtob7eMl9nmLmRrG775z0XVjC7yra6aqleVanY1kr79zclAp9Ozpqfu7hQflZ/ai8QBrJZJy496wyJBXa89Dn4yeD6D255IPH4v4t4WPb8VOw92EbWE7tWxYNUGdckSD7g9oV8Y+2ydbCSlz/dfoO/MyQmUT24Ryz+I+PLnu6XJ80D/NWgP/gyhyTt2syPNIJeREQE2jlsuSE2fH5+niiVwvm7p+fb4mGUlQqRcZ8bGlTiUwq+'
!db 'GTOueKF+ZzPnEk2NBoqiX5Rgf3+nkD5/oxbtNnkl3SikQ2m0uSnxaxRtAssUJ1z06fQoBMJi+3M9wyXnzZcnhKYIAtotciYM6yvKUZzvSs14DpA60I8MiiYdPP725PWM6B1PNOD/EeAoCtX48fc1e8uj07XvZDe/AaKhKe/5+ZFepH8zG/QYC8SwJw885Fu49mjS/k8mY36ns84fda0T7r3y+/mT1OCM6Jzq/dHnpLL8s8DU/7PBumVYz9OvNIww'
!db '8BG67GDzP+4qsdseyIh+woTxZUEvYJIy/weKz5b2efW0beUnY9IWKNS9PdZg9PnOcienJWcUDpYazvb4ySMDBbDU6WX521pWmeGUlJRgbOIuTksfn5sg6XRVuNoz5p6HtDGu547bKfTvZC1mMW/n7js5C8QGUelLojR/6IKxmg+Ar40IIaNETlGo393tVehpPqWSO30ZqNUddY0c5vMKPzk5OUVj/s8tLK4BeLNik5C0gLurxK8inkdLQRu0qRl7'
!db 'WBl/wLno6elpdm+Geeub0UIz9+lMld/ucdyti1QDtcg9RNVb0enO9b54FhPSuMvjbDGRLEjuC40fj2Vot9H+5lOUiBmEVhdfFWv7GJPGsVu2P21+K0pTeVbo6GRkG+6URG+q8sVWQD49JjbWhMz1G725ypWXDUKYdCxRqZXGNaDLReWfOT0i9s9/Wn7wAmD6f90l992+tjreB1/jwMcnCrWRUjXQCBVSrbQTuHDBTeamazKlWUkgkzf09JoIF1jQ'
!db 'B5x1tdWU+J+uE8t5NNX39fgtMZ/mBily+e6z0826x9sWexbb+prdpD32YVlc0PbSQifRZ3OFkDqH2Vovvc5XZtTFjcV49cWL3M1fvIli96mi7LlHX9HfgRvD5iZsFMprCGpPsFXhxyvK6c2GHXm6BxZ0ydzNlYgsGnn+1op8iH6tgMH9lPTaqrCeHNQ/RBGdjFp+mwliKf6ATjkNoKTun3AlbvC1yYWabrJN5mwBye5plZXTcwQvnju4pJbnnjfP'
!db 'tByTeAXnymNpEbJt+h+YjwUc8B1QnwSh1KzP1cL9k7zsIodzE5qYOArwsgY7CDFb7POlxrAboRE8A5Pw07Oq4pLAhJqZ4tYa7ftA7kPdBPHZKp1YEfOL2WI88jKdAT8xwvDAn7Wyu5DR4NO9suz4VrOJn9U/qlx4Wm0VC6AeAUYOdGDfX0nL/LqqL/vzC3L6i97DDKbckXvLpJnY+KorP1ehxArY28ldj+Nb7SJKzOh/GSod1l7EporkYM4MYs7o'
!db 'BQP5JKJs4CWF/la7JXz9kQtxJuzm6OczpXWyjKAoXXQ92c2AdNr/pVjbbZ1yx8k8DatFJyOx3qm13SLqwjUyqWnaMoqASBbtlp1+g1ZNFgZu1dhSxGEJn5YNU3WFsnMmz4OsvAHQcYW95PZAk0xjn0qf38NJ3X94AWCze3wFnFPAbYoZn3xS2Cvg63IgQSY27sj2QStk+ENidVEN7+X07Kgg+/hmwaGBQQpfi1IVuzgbfHiz0P5OrXrz55iXUYVw'
!db 'JSdI1PZRpkKSaCWH/cDyvEOjnKFjuffxatjxjZyFYeEeRDvSQiX+RjhLO6rsD05ePrjPWilAHbXO2uA5pv8QDRVljm67BmvCOOIPotwPF4bmnY3HtoonD5rjF49I4t4Nxy9fbxHak1j4WHWaj020sruh3pDEWa45Iq+No3c/5u7v+zUOSU2yPy0vLV5cAE3LxddnEdGVAarzdHV01HspMsAeUQGXk1ACrXSqr6YqBWYfTEjiws1UFuj0GnB2nCBv'
!db '/bryLi4C8pTuI83pEkRBVvaoPQmLQbIAAXftHeWAe3/wqXL3rV4faxCOnAIawOX5OElLfsqnPIhkbzxwLl2QVNbQsN0EjhV0Nd/kdpB8tbvORxslWXcx0xT58VydLAFTxANvwvDNnkPJYZ4eiUYYO40htF/f+9T4msyitkNncepHCVsuq6mK2M934CI+37h1ZaieR0R3qf+Y3G96/hsDk+Id/JrTYXdSvSZUrSYY032yFdXmrxan8vxn1bMKKKyp'
!db 'x7Pkru586AuTmqLQhK/jXikANcOmAxeWt2BhCVXk2b9f+uReiQo1zsTGG2FhyosBmHX7azplmXtUNGoNWBU57XkhX5AARaphJ6zXjp2PD0Z34n/ceXIh3VuYsEHA+hDvmU+P3CK5S1k5/dimAOVHwsz9c2fLuwv2Y8QBWd3b2Ju/2nXhsQF1prfalGw8Eb6VhctwER7BIeeiM9dMnofmWchH8hlTbghIjKbIMlVuRkythlrFqbaNfmTIdC7ifF8s'
!db '4UVWVVN9Yph4WXaV4tP5BNlVV48TChfN2LtRlHK8+UQCEecen4eu0aD8QD+cyJuDdneQRnb8rP7rjl3XhBa4rSDNN95ee0nqi16y0VJj1BGOs471V60tANjqyIVwm7tvrKaz7TuPQCrIkcwOCT5Ikz38UBncy2lZ3I3LqLprkr9SDNzfEkwCumwE4G5k7bkCFuNs5oQoxBKeHkRnUu+cXsft/M4xnZ9i5YtWKs1Zy5lFRQL5mFRLz7xu6hcxnE7x'
!db 'HS1s/2EgOqE/G69K6BoUtqraFJ48QnzDiDVj9ZNr6bDGIjHLtcLwccB5om+QCWc1UjdTOcj0brSKmKjoSeS/YmYFkyo67tbjWPvigsXKBodffpN+D2Zn4lwl0cBLEE3aQ4rXDWQoMHGaSmPQ2aP0MdalMAiHnOtxwrjMIKJuWCCieumvXwsD0F/TmvSbveBMwFxl24REQwSXBkwgEPCXgMkuO1EP4SrJ60U/bWks1+HXtYFtNtmcie/UX9LNG3FB'
!db 'RM2sucBpqvc/yEjiHA8SRVObt6ybrbMFyo1PFxMdWHUp+TnU80EGpjUgwV1YmMF51nCf0LS5rkt91/DlDuNm1P3mVnGEDfd+wM2GiRLdbP3Lli67q7eZG0cHijfBQF6J8lnJRe4ZuIGfJ2qn0on9it+v+Ds3mUNZznqIN6mQu1lJFpnIHPIDf9C3wfMoD7+pNyVt94etL21KSwq/ClZ+0yWqS/M3FE9WTzdRKWq//vrG+exUCjPVDnePYf1jSMt5'
!db 'BxhXY7aD7WZsEZGCsg0oHZYMsarWbm52GfoZlPxJ7y5EjrjxzBgBmjkqb0FPxVsyf/dtOtcko+smwLjT9bDTjnyfry38JOleKPGphy9e3w9qeVzLXrduzRpZIZ45oflMDtTjhwd4LpWi9Nqv+v2saXJJDf2NxHXViFEtWe3KcXFi2KZ67nY352sIYiW/DpC3m+/AnbqqKsVtxPgKCF41415qH+BjaEYVwPZ4A/af8RA2ba+krVx40lx5sEDOiWU/'
!db 'OxiaZ8JIy9jcnNlzXx/OIJ2RV9Y3V7Pf69E+IfZyJiiMbzlvWaY227r9Q4fEF2jsylh8ABqoTB6ibi9vDPim1yTmmTczhnI2ncty1hpxcR4l8hKlFwad7LE/tppHzgcGVmzSoV3yh+Dg/8pBTOLgMj/R0laMqql3DeXmuc5/rU5Ey9CnMVKGezH3miROfx/m4iEo/tU+0GZ8H2so49HDO7xq0UhRMQnqCRmM3ciwQx7KKQFuueS2PvrZJLskwjiC'
!db '/gz+VqOxg+PyygbiQcvitGHNe4Swve9zU5V3ww4WYy1R7nszt0cB98V2xZZ7iqI+tvbWuCoyGMGqMxLlG0eFpPyd97zn9HUM9cT1yM+/O+t/sTPywTN2bkJCOspqr3Uwcs1JNPhz85O/G4w1QQJm7+8+sRGg6GNjzFSE5dZjrF9EyXavxKqnD/rlCbx4Jg9BG2vZ9eguE+vFK0N5u1hpl7bY836XzjqKj8YETKGyp9Giz7cGTY4BCKvi8O/deW80'
!db 'h9zibXnqi+2x8Lo9zovgQ4tG9IL61FhfzejByJuazYa+vkm/tpv70njb64nKkZXxHcCsVYCEQzMq2eDkkFmpZGnhhpvzPE/pBRiV7H6YP29C9SkWeOVZU9AyA4ryp3Iq2jiS5goRqPu+QK79aiW4urQ7YeHj76g6RMfgbzslIZI4vrbdzfbDiu1mPbZh1JjFIYPv+d1WR4D0FgkBgy2xHij8U/iGC4v9CyX3eUl4jeTWI3rKNp6du+gWiw8sHhvS'
!db 'yTheyQLTDlyb8VtcuuPQvw4EY4LaLBkryrhnIrVSBL3Y9zpFSuPPvQXuhQtqG/hO5Qt3XHFrn4R4F/HNT24Xvxtjf2y2pALA8Jsvm8SO0IBxWxgteP5MGYiq24QwYNbfhGMUV05Z4spm4k5OXGG7Sd1tZBtunXTM97a0FpjOmttNbC9AiXCeEzCMz6FMJzUipnks3nyyMVPk4ns/LJQtgusipctPuGDxbjbCANFJ7690qGkNs8zee9nA7lHlT6OY'
!db 'PuF6JeWbd4M17YAN8k0s3BN03+4sayzzgKbiUTYK6E7lEjcekMpNADoAjJVH0HoUAoi/8ekkTuenpQNudU5x84BXm+w0Ngchs+sZwagGyXjWo13SWFT2vEdfRtVmeZY1EIyFh0QHTTxDLsJK85QkufcXSEO3OoOKkaLa6QYejgJy/yahuhUoyfjPL8Hb6MzeGHL6AJ6Bnsfp5zU04DDiQnSUHhwgYQXrmqywFzxgL+CNhogGy1/h9PlZsYJ3MvPk'
!db 'WcEwem0Sep8wY0GwbhgOM+WaI8nrxgPYwoc0UTfnPy9JtdCRGt8h3GKpa/0jlM8wF0EreSXfApmBugPBo2z9GoXoeWkVxrPjnI2ejmSgu76Fx/E3BjOpR6OXvquDxAZ5xB4V6Vp6AcMOfjJmurG/hFE/9LSgXgnIUvFZrVffnixaDJ2NdjdyH3rbnNU5RAwJn6s9ko+56r/KskfcMxbxcnu7JKX6lBgPXLCMMMkI1ttDHWYG46ytCO8vKxt3/mr0'
!db 'jtgmHDcit2qWKyUOH/xu/4796aajciMqUNOFxXu2Cx9Cmytyz5McSVEuBL1HWdQbTHpz2wUcekHeEjqzcI47w5V898hvnqLyePpYYa2VS4qw40CRRKoZEmcjc1PA3d+Uy+D0W7yyhTalkPxch6G0VWqX2FA1LVs/oLKkl35di/Bmp3paeP7gon5ZJSvHptDp4tE70LJivOjTfxEdbosp2aDarHHec0XMRYe1ddDPB/dB7DZdkrsHhgQTi8ENtKa3'
!db 'ZW99cP2EzgkGf5Yrexdm5V1vsPPw1BADeySCydxLnR06ediL1hZhbywFqCzxS8W14PMlEFCpiXhN4DMnwLmjZDCEqjrllSVNy8/u4te15GyuRKviX6tcw6NuMkzVe1B0qQuXP3JZQctkNyWc29+9m5hl9KuuAj8bQEoZ45W99Zj22r9zeYCe3wu8JdWRJ6LHLe0jx0mHA+GvkMxyimovzIBMAIp3WHo0kumZCMb8V5jGtDs4fR9zlefNrZh5iM4j'
!db 'sYqHZx9xvGL3116rclCqlN0iaP9+Vl3ovHgwW/6XbuTjVFv+phu8ZnY08no3byzHMNbXm7CtaKtr9RL2/f1jPtsZLacbPTmPlvfgBrZqXp5YZ4fGRDOVsBXNNz/sDn7ynIr8Q5m8fdnzL4FEVjAO1j9duv+1LqNDcFFpqZDn0WeF1coX0S60BBrZI2ubm92cjNgvB/irDf/QAP+eOnlSaCb6BVpX1825kkOt8r9zAPQg6Xezd5qTFmmmygpga8+T'
!db '0nJMkbsrw0ifDS9zPktare9EXn4dTcEfAFKNTc3is9R70OoMbM8PuPzt2Lj87xfXzwSMSV3b78ghohPHf5QUrl8wPKp08Pilw6hTdfGgOzp4pLI/dIloLTEdIOD/B8bvjzaW2RSzjNT3ez4KeTrtHkr+kUBKWtrCi+ZfvBKz05JfoPzbReaz1n96Prq+j3nyL/bJXggTGW7Y9MFG1dBnH5ksen/L1m3BsBX6iuGLSIlhq/8kVGPq/4Ny+beGEY3s'
!db 'GqAPDh8Kt1qCbEAgLIBMl3/JGYZnZmaeRyWsr62x6r9Zfak6M8sgyM7YA5EiyHlD+YdsEQYyyaiIupfKfBln/9LFaUlLLmgCy1UrM9vT/TA/KjNaaLa9pxud40JNGw1iEQT3Dek1no8kfhVRzEeHOltw+h/uBEPoD3cSYDkJ0SrTJxnL+B3V+O7y71uUPOTh4enmtPT3918LNDkHY1XZSBLkQF5y5onSLC+RjAHinQEmiLBtiFSMEkDeAhFGm4pN'
!db 'HbqnG8pxqX4hBWq7wpeh2H2xgJuGv+XRFrW3udGpeIr7/APujODommbw01QUIIJW5sPUEE+ZQSyStptzK+LMZgFnGTx4V0YoW6ArNTz1NIJ2HCq/tsR0rNtVRtiI/nyhLqQH/a4asZjaVC10eOyN7KP/XzP4P+siRJG5JX8jv7/ce5h+rJruhBJBFTA6R8f29Pr1s5fNWupaoHazCu65n22NGVLybQo6t7A4y0JqjbN1LLh2L5WB3M2nY1iNUXt3'
!db 'lesS11StN6ePsh5l8jzKOt9Ouue9uDocPHWY0CJgKiFsNecS1Opd+zxwleCrt+HxjXU1myxit1RETI8oSQBxomgyocjSt912ki5C71poNNNlPVznmTpUc4AwwiW04xv8zmXtfTwvjWWpaORIb80nbPvp9Axsc3ciin1RHaUY3+ivtZnFfxEkaeILfSV8U5iOKpfKDAe4qaJxCUwuZHZxj1KFlLBjJucouAzoo56AEhS6PFPDLZU1AcDKbHqsBK4a'
!db 'srdensvSnBG1v8aibGDr1DNYauXq1rRwoGyZY9cwndyuMr1l7Y4PT9Bj43bbQZDUsLv8TEkmPhr5q7U19OsnrvznzYTvax9qWbjFb6Y8ttoLa0gxa6ZkQPLvKqWoQt6MwySfrjnPsLnYeUlejXJ6B3GBpEtdCuD+K9+zLSMw4lnx1Cede4oG0z5qZ8cOVcb9kYXANbWn90gt3W80w+NpYE9bjoIt4U5dmoip+XXjUk0qdvxaVv89Ann7uwWwtyTb'
!db 'BDlfO/sKp5BVFeWnui49l9zF+Z2lSZKN2Dxl2KNxrl8B7jz4jSCxBPIseIa+W/r4VDzDfh978ah0NMn4Okx5cOxV+YL2R5upq6vLdZpNmPC9S4LJDU0QjvUBi351zQ/I10GrM+20Iz69Jvl+2FmljmIp8VDAXeOpkk3w1QaISZsiecFp+MWyCgDrYQtT+gWhEw95H5VJrfdX8nQqvqMGuYtvG9RA8E4Vj5Od12mxPHjRyd9axHnQK69v2zPUZrrA'
!db '9ENiFURca9+5El61NG9hqpLVkZpg1xebEK9V3C7Q60Vix1dWkec9sX2ITtNV4CsMDKNJpfjMZFHDVzTSka8IS4zUr6IQnqBxjwMtDLertejjRrX32hLxokn+ZzavRtzfzQqIoJxLihfqu4qU6vYEdQKqAru8v9leBlpdSujcFJZHqjs/JMwAJ0yR3/utT6Q4o8LvTToG+FoFhzP0u0fzKwze8XMkD+t95NS326Pt/7kj/rSrG4yqxQovfN9xrRp8'
!db 'WHQMV7YCZxaNxbfXrnd3zZ6YiLyPTKlxTzGVb4DqM57R/4rLK1lPBiFJF69O9K7XbrGKG0bzGcqHn4ZsM1+PlIdfnjqv5mya1azXtwXoXJVvam/FuxdPL3i5CFvz4Vm6TLvFBTO3Wlfdb/OKdKsqRxbHJ7PEJSVQzXzsjsIGidU3k0TRjhxStIgK58p1L35f246JWWP2zWWSeqzknmN/RPJqbeamS23RYDJjNlVHNux71rd8xo8KGCEFQ5vaRa9i'
!db 'Y7pYYrh0UnVlZdsOy298O7Kf2wYPQ1NSaNWzAeE9cbX9JEvAvpa9s1ix+x86iq8ODf/aygR04ydUNyfXak1quPHp7AzTFazz/oiRKJTLLb+/7hn2rBM8uJw7zM40yoRjqCd5YayT5T1JlyvFtevoZa+V2wKAG19srVxjVeDIZQIob677xMfHR3KV1cyBohh01uI044dIJs1QWaZVQiZ8Az0GzPKMm2aabJPFrz3dWp83TfgGu43ZzQAul2gszaeD'
!db 'Ed8cA8+ICQZyzZlYwo87JiZGBnRZbIq2+a4rcLBqyTGnnHQGzFQQXx3MVR6ik96XqE++sdW1fCGM2uU8QYOmJLWi6UhVvWzl7p/cwEbJDqfeA151WRZm12lY5YJXmb9zrUDoOMcN/C1vAgJuzc4ym6ESrGlu7661uZVR3VwZnQKOg2s9AxVpMU1hSc+SNW9bwt+9NwO8IuQTFtnmdVm7DQuLgLtNvhNjiL4cm4qEkjNE3ldliTaUOXUq+4MkIu2d'
!db 'g1jFAN0PU+UK9Qo83KFXTajM01n+1OsgU1T7UvAbeChycv5QtzuB3yaSd4jqSpq8MZh7DEcu/x+xfctwErijw084nV06IY61cVYEp3poGRlRUVz+bneA+vKbqeztBSJ1a5PGvSqH1r3i3OMMHz/YT3L6EBlVRBDPnBpZD93DF4nEx8WtJqyHpgRBWR+pT7JzpW5vURRmEpIN8JsQ7XAKV/o9sNM58y5XcUB7Vue6PaJL1pl63Jn8zRtSerZGXS0G'
!db 'uuCIvEItpldNCF8DYlX7tU++LYPhwpvzT4N8rPJI4rRKUw7JkFfts0dHjiIIwnQzFTEHKgXxV/AMftgZiwNumzStMvVdJjf6+TAoK0GK41u6WqKXK2KdWod4ipRMS+PhGfVQ8nO7nuGjZ3qBAEUpPSIwk00SebqAEN/mdpv2CBOPv9OibRYgHIQeYenmduZJidiuaSkh+vk/6ugI9E+vkkmNI+fmb9AtVNhqPdjFH/z9yddlXIGDMbIunV/a7hbX'
!db 'BHDRMLJLYX3Y3zdIR3jtH9qTb8j3mM9tI8SfkjtBM5NaYPcvj/aPBm/VBt0T2FJ34Z1+Swsxcxv9WfpPEa9y4ilym39fnJEe3o9MHZLZrvIHR7NrbsWIn9GXr7fZiq8K3OtaXExEp6f5nf8qRe5GvqC4svLZIqsRXRuGSJaVjehcyFK4TVAUZtPcE8CWpuHhCFSI1Xw5cRZkNVhYu9ixsoPrPky/jN0FqWSN5NMLBr6ZG/nOUfDF2M4jJNo2gbxG'
!db 'Qlz3IAKWoJ8mSraN2JUJnu1ZWd5yjFQx0BoMeqjSENjUL6lT26FtuxmZwsTIkzOStWRDj5Hyeqtol8MiN5qSLS3xZnQ09IBjVJtH8Os1PbMxcm5WvBnXfXQTrnm1l5HqmX7ObAN3h7rKkm5/SuWeaBQStw1241dDR4n2VGs+DsP8MTtWHpxYvjWS9TwO6aaim6ai3C0EsQgW2kA2uGd6Uh8htV+jtx7buUHDeLS6PWu/nq0p8acCs2OTbouiOtXe'
!db 'phqWzqfjW29Hc9RnYjrXbJ97Jh9PzjXYbZCM+8Ew8kOBCAEZ7V9cJs7jjT7x7n13NhTL8i9eOrm6RqyxDm8qeAYmpPgYuUcv+B/IIa7YRAIqbl+SDmVcBt7s6A6Yi2HQYezN8APaZO5nETYtaxkMYMRkpHxJ4UZfXMMcwqBzRopBgKo6d+/VIoStwUfTNphq533cN5m5QgiHixvsnc1V0CKv/5WMz6Cau445FzbIs14bawQiqeyg35c3LLV9mULe'
!db 'kWAv+Mn+eYtIAnqb2tymHtoyu2Yxm0Gwgq+H26g6sMMU12zJjuoyhxbmuE8NfCXxS3AEVRhvdDqrQ77dJSWb+FfM3a6mCxoTeM++tS6Z4PbTScgdZWzvRpJcTA3BAW7rZbD0hSKzd8HRcV1hhib1VJVLMTlUqN+6XlkHsY+lL4X1dfY4UaseAb9jzIUdgOzlOInY6mLW000rVpMQxFJt78oHMwD4dQZA/iF6Y3FsLlm8QvRF7FJOXa6eeAQo3MIr'
!db 'U1u9zikwg3Gbn7kMn7EzpnqtouKykx0HWOErRHHwkKvN+alp/psWyWkxhzcKIV8LjqLzeejXyWLtE/Cf2lxZPS1eiV5KoQUkiy2sYxpncJDJ4+y1+h+Av8ho/tK+TwytLUGwca09A5kmQgUQzvVfuNa3i26wjjFERmBjf/b5SEuiee2P6718pvXT249ryan03c5/sqxd/6QSneimhwggIwEu+g3jyvfLRw09JC9gKS/svUniJm0nCOZFjMr0h/Ii'
!db '1rcevTPY80yBbrAdXuJyGcInWyUA4eSN0Mno48xZVklAd8jfd5buy9bF32BOne6Lycek75fUixSwCodUMe0JRuhG4h/A4PYwX/tRs8hJeVsCWND7JC8x4n8S54+c/32V8rpet//1aSs5VeKh87XJDcHazFWt2wz/1STCAUPRRlbIbUfjj0K8RiFxbNfdMNJKRljC9IN5gDwDyOI8nFq7h4ORJk9U51sDGtuBWGLe1n7PQOPDbX5ezy57+Vx9+FSt'
!db 'MSw3towmWhfytwScWIxguvYP0AOLlBq2CucFiqfyOj0StaD+d0J3eYb/pNF+KB3Vrzsuo7dl9TD78d9WKGD/2wG8Vtbw04xF0GvYk38d2zbEi6JWInjMATs25VERtJX+KG/l86/Tz6+vbUxEFy879+wKK/535fz/e+OPpv6Drp3C4wvYfHNzc6bLCRoLz7QnV+TO1EzZFzZ6rPwjeL9f+vJEMWXo9zlwF7mLKAO1UvJb/HV8Y0KqUabSs34iUE7T'
!db 'M0ifCpL/kRH9ZLoj9xRfWDpyatQKPjqNRoxWWmrCbKvfKMYyqgMePB/KqJnp/KOVv2OXz3oXaRhV5ocGf8qpwlzLVD9RLGwGf8T4tuoMtoV/NPsn+EAZFfcCOSXZSKvhTNGfnjnnN+UG+2gci+NekbYjA/iv3rdNhuD/9rz8PzxCN8+NHMNk4w0B8mM6DPTNqsBoXTSdtHp0F8e1BabGLaatB9V1T8bFHEglykN7juEW+LyhsPYNCxKEHWdZ3V3P'
!db '6walrXcvoh0a3HXXlwzXUxXijL02GgTp1ovpdbpNpq17Lex03DyiP+N9asmpyaiv+RF5WHiY99XeHsI8VNJfLWgy8r18bK+gzKHI/lJrq6r9rJJ0/+7z0LEoalQUVbVJNRD56aGdTpOjAeQteWUnbRFOmOwI63jPaIJpZIDSQL+i9pMA8p1d8nNXkOM5vreU6XWccCbP8wOIWHLrp3gHzl37QVXr0whdwE3betPcuJmIMr5wM2cEpRHutOomufOM'
!db 'su/Be6f00SAgv4RRItfkhm6IhYpocG5uCeBGyNa6QSVd7QdQPdeispNyU8UQIWmxmGHxKU/5/BnIOJFa08C9SKpT11JG07yIwGEtx1VDG4EpwnJ6QhCrjp1g6k8mCALLnNWNg5B4Bkj8yjxvRb5jDXRex4Y25gXaGLodHGYAj6a5Tq1vjCSr3wl0XAthfXb9sllYZwvwpTFvfF0vbrd0PdbXb32nyrDsZk3Qzt/N6mEp01t+/6uehjKOgAPrmTsZ'
!db '6sjxlfcSazaFLjjmCWqiTAhI426hT8X1GEZS2Fr4FU5RORxBbgtHnF2/zsTG4cjth6vm50mkREkT57nebVJ1t7T1KwENIDEwU1n6ZV9W5pJCbj51IL86KySu7Zs634xz0y8vHTHH30QJBeyM2g6Gf2HIcl+paaYFKwogCODZU+OsZ/RtzRbFO669g7FIBjLLvfAK3D/IpsI95XqHN/e1imjgMF0Qk9c8a6DzDzOnvLu7JW3qJGwmjgm107vP6Xcn'
!db 'db/Ni077bWeuGC+Q3I23zujAX+/TJ8jtV/5r+fmWTXI1Vx2R7+zwR1tYYfVItBmtMpQ7GRRXPS+x9UU8zpnSDxiy1ShBkY8Hot/BNQyDkt87GkQy8BqHq9RcZGD4zF5fFxXd7nW/5iaMI2IJfS2WQGkum+7hqbGuXTBl5C0YNUlH1zuBtfMaZvmiNPol6TOcXMtNBnrmbnMnj+9mTK6AmY4H34LVsjXzgXKn+mXIPtOHOltXvF8E6aIx1B89pApI'
!db 'Jnjw++Hm+mUgDZRRMlXUa0bIb39ijlinUIJU0uoDNTgm0n+xp2AmX21xJ1QRFkebhBVFF95Ta/P6DblC9IC8/nvhfnmC5E8YXN9wmBcK1MbUToltBNNrnhDtYBItOIEaWD9Q/2B/88sj6YHxl1Pn218v9eKyYK6w+8LUi6h78r2ii7tMdXmAF7z/ik/M4cGcAAgae+ia6pt/Mkl+GnbChQ8RMbb0wFOz14JSu9rVqln1DF4XNI8Um2A6zruC21h3'
!db '8XGu9NM0IoCSRJNU2vmyyO+RnvqpEtMeN3VG9jp3axx8YOIqigDBtZx+jb6meW/f1uhNbhULt4t8Km4FhkcP+vFSElapIqfece2zpcdyWjHrlnjUb+KbNTTFgR0EVqTXEkW8UaOSrLJaxXGhC6qtPLYpnZnLy/7lyknZ8nIQRYHX/bC13xIx+TgNmGURQUJawu95eX+ys0mWNaFBikuomHTYmZj1zqnrhNv8toCcZhqfeGr74GRC8S7ITgiYiY33'
!db 'ILbNi69s+RvAfGwwI0Z9LEadeGubHRcf5leiFbzwqN7CXmQjSjdpC40rrsU3K2nc0ofKNXZjPtxlvaFlS0xnlSchx9Fv5CbgF3nPK1F1xcRes1afIZPfv/LIPWZ/t8zueN5I0iwtV2VVBzJ5s5CJIRiJ8157uYkcgV4T1Y2eD979wh/MHwHKyIqXU21/DrHatKRZBPx1DyypXOQZP1jzfsF4fGL68ri+GVyE967lHiDw7GYuTWM0LyezUVq/Bz65'
!db 'pnfCxNXKmS7H85W1Z7HQw+DTepPjlqvFEer7YrbI5ITXxdxxCu4DF9JB+LsQGmiBYpJo5cwJAhELBEVHDyJPSXZO8Xz4b9RqSZiYklSf/OWpolKyf/A+pnRBVJ4zR57GWd/5Am9GtlVJ3rphuBNsyagRl5TN0F1giFhQ5Jsjc7vpXVymVZRydsbgP+4MFrbQc7GbUJERUZT0LhNLSJ7UW9+DzUys05kZ/PS9y4qLhGGUj3Gwuno9XLJfbmL1R6+z'
!db 'mTiSuHSfQ/PHhOrm78Gk55dNAApKxd5bUx3IcG6IjppjOnTEKgeeQJ7DkkE3Fw1b2FedYboJ4W/XBq1kqMQap6XdCW4NmZCMywHBJ2o88IzRGll2CvRgniprCyTrim2YAjP7rxrCKSYG5m+x3yDxrdcDO5lSQ45A9H8V/GsMuq7Nl7qR2nXDDAFrAUqT6nJtk5sH3YTac6HkpyFVlL6690uGd77i0VeZfzWonI+BhijfXVvYh3pJNlx13q9Gv8vE'
!db 'xlU1UdRCbl2w1hLrWouULpwyPV1UqDDa1IUoLM++KJRRlu/tRazl788df+qZE+WeaPEomJbmVXzcT8fLJk8WOeUyhXbDl9zfnbm5YN+I49ZM09iwgPj+J7I/WQl1+nPGbY5wsutzKu+F1O5qElo338hFN2sQ+s4oDpZVDpDB1zskbj8+Mel4GNjDeFqF5UqkSbmYov4thoPBp1LP2ZpoXY81p19OUo+IJ0BZj0cz4iyGZQrauDv7Vb1AgM631MZ2'
!db '50yVij/02w/2xapvoxqcXsr6NWYj7V46YehZGs3EweiuokWUIIXEdXO25k5mFXMgUKASUMsvZWJrGmNmF0ouWTfPDMfiyO6Da6merzBNyk1uTQdByTFvy9y53RZv5+Z/DQ7ZiSVgHVC7pekoxnkk51rCs4JPq16j192706B/qvUe/GX59j+rIF0h8ua/HEtbvTlpDsYHejLmHZchIg1Qo7XryOOMGuWtgIf/umSZ8j/UtO7v71dGEpNk5eauj2+r'
!db 'f8DtE1NIXD1wG1ufsmciNsZ7knpmaHJ+3/b0uTfqujazLbFrDf0BGm1GdmOyWOwP6/xf9mxHp2ufPCeV/aNQvV/6u3IUypoKSHWlCOVkYUpPcPqNTtOmRf4KMlOhaJrqSt8zpP65Cm+egMeKDct8uQVjE5yRCkD0W4XhoutNf5+lpCry/1OdWRUiv0nlG0lemTsGya3Odcl5g54XRrO51TYDdw9pjVxdXSE8zl/QiTC38L9sOyL/n1YGtWL+k5q9'
!db 'JTIZEkUdvGs+Dv+TIO+WN9+dqR2EoHPWId3hVwxKTwJ+KA3LjE67bz+JoE21S/jPGhXRtKOjozVWM4kY7hcwBsFtM+5kAJG8AngS/TcxETzY29urU+9ohMYSdXXKbyAmD9nyRKU9PQykf9gR50CePueXtp7uCLf6wCnYBpazCIikTTWn+18HNT9WE12VXrmsNbGmCum/Q0wZkbyWTydiA3638oQpvGJn1KodErn3VTChFPR0FNuvKgI1OJvZ1sVR'
!db 'zb4/oynWlXy9ChoMWjxMr8LFrtr/Ml71VnRTBlCtruHi4qIQHp2eTuVlnYLKGJ1Op5HN15H9N8RBsMZLnzr2m5yPTd4CP6GHi1vqn1+w/a9WMf8Xa52NNWzc0sqal0zVqS6o42WqjTbVkyR0jFj89Az3C8qdPVn1AFdy8mlyW4pgK2tez736/annybE3GRZj5xd3ZT8K3tvmivid++MmpyQvMFZv9bFuixGTHog9Txam9JPXc/uo/Xdt5+rpv1OX'
!db 'worx6jsmH6pOBdSvbC3PU1Gs+k9WWW2SJE98tF2ZqLBSb5fnfidwMfLpuh1ebDB3vGGdKY87BtaNNDHJn5nRcznLQ5rl4ZoNsRmJ8FRuH6ZPDylNDlYsYoEwf6/usfjga+z7NPJPaYQqOET467enF3lZwl3G/0RuRSSxt1+OvB5Eu3/0XWvCrb+0HbzAgGYsvyj0q+BgZktZ+GCL6FCFQvreS+/Yz9cYUxo3wQNCRdqQT9CqlEKEZPPBT5Nanu/e'
!db 'tbJDJzkP8+1+WYkY7Z7zYWrS57psfBB9hrELZyGy1lrLayiaq4J+/H3yIJ1z/48w9L6FdthdeHiB2bWQ2rtk5prlgrLWx9nytAy0hzNnlY+ntx7YMcNwOPReUEWs9HyHbX8i4LM8Yn0YautuLfy/hKt9L70fv8UqMGOSeadW9V2GjYFbdcxrs2D2XNJuiAD7hnZTSwUNAYoejZU6sE/zi3PPOi1aYEOBctlNnJl1D/Im23QPlx9H7Lu2bj/d5X58'
!db 'M65EsS99obXAyGUOIcVFO+kTJ4mGB+pplK1Oi3mSlyb3RSiM7Hy8pufbKJhEwzChvAEK08pGGI7tqgctvKvHZgU7T/hbnQIrGeWh9n4pFN9ETMY4qCaL4KxeJiRx85o+e6goJP3Yj96c17Bfjgk4kxTKEJiB/vpCdXdpbi9HwU6dhzZUje6EXnWHwbp07iLaBgn0zsoyFhCYp8wjvThIwLN4A91OJ22EmrMMF0sj4oe53Y+b78PDss877u3L+X75'
!db 'tV99wlGBq/2yUCGD6rr+XpcJqGpeXLrbg+siDPUsBcGjhCUqdoyz3qeRr/Tyu+6mp4cI80oXmSQw6LBS9Xf9ZvN82nTPViLDJtqgvrzL2vFJpn6fBcFiemnJed54RbOKiwb2vWyyAwP+nMnpsQ0/ICK21NIxCJPdNfOC036+KOE6l011s+IwRTEH/DnCA9+55ZoCDiS+yOAQo75MlIitk3uP38JSsCss17b31GfR5/DQH4YUCKB2dVouS/XrPFtF'
!db 'I7cfFdtCWdhixBgHzZPYrufNIsNKfr1FCOipi9zk6DnCnTTKihyKf14ttNTcpUWoFwgAke3RVKFqNRcHzFkqcpFcYglUWYG6kLfikWqlo4teqd339ruTpYd2deP+nkezX2cwMsNx1IsL81FU5Cw+bsdfuUyaT77YJd1lWNv5HrLOnKS4E9PI0r5iMmMCSyAwMIOAwnNkJUoTzLkuPYc2DisWZ+fq6o3qrY6Bapq8Ha24D6q7RD7OA+u4aWTpqXzI'
!db 'v47vrbCIyzuT3BfOEtZH/9J6f4TtidHAGl/64M+o0tImBwPJnselFpM1PnQjs2Jm1i+4cFs48tTzCQJyzkV81nNnmHtWDxuBbNY09mTEfNOoissMGrEJ/HUWQLbxDiKa+9VCZeEYRy4CB+sj5+3DgxndvwswW6FK64Pd/GpP2Bqnrjw5A0s/LxEf4WA1/PzntpTaepu/tgT7uHOUo0ULuzkYDZPlt8Q65p9BzTzatzwxgqGC2opI8jgFKVjNuLIN'
!db '7DVEvTApKlIE060pSW0zGkPWMeVz99rZ5kWLqs+e537IkGB1+q7fQB7PuXCkFPOHElkyjzSSeb67afea9ruRv5WQxBL5yKJiZNbApxr9YjhOamtTj2Xjch1I0Adi66/bpfUM9LNwrIrQ3+24xOalgCJZHjGBOYW1DqmvxGCUYcDG6hIDCh3WLu4VSaSmw9mS+MvmW86K2aoM/XMz1gaONzMM+KW6rkyZ86qJ0b4qK2QvoMVl6lWbmuZYcTV4UwIT'
!db '4+SVEWfyVnQOY/8gSe96vJz2xrFqeyrUwRfBWeO8O/k6y6bD1W4t/EKEgxVUY6lDaS8u2/W78nIugmE+QowYKysPAq+/o/pbNnhYBwMdkG3LzriCA/+nTFIe9fhhmfqnPzJJZTbKZw9rWXGXTY7dBDBhtt2LF8Cp61TOrEKMUBV6eOz4JYbrgTpZw0tnnvsrsntiTUxm5juZNSf18rLxgglSU5gCu76kXlpjXh8aw0ybMhWUOvOycXI7mnzK35o2'
!db 'Hcn5wX4ceREjKvgJoxO3xgPo46fj7vg5PU2X26J7Nx3pgBrkMlUh+FJ5+RugSa08MNww5Ir5yMhQoWps37LrEQijEToJcIyAgZY3Vz/+dfja/AdL0MKDb4/Qrqb/3nlxcYjwvFcxWQ2ZDgeC229IN1s0aJLdBSvrViyRDncoR67kbADdflEqPQAQ8xKe8Wdilm0tFDTeFmrCrSamMMtMNjB9vGuv12psM8PxL8SU9fKLz8ntrsnCJXkmpd/Ot+cx'
!db 'AIZq8BNbLl8J3dUPSz75a2saCIURpdKtdLsbF75HbIZDrBrS3i4SNJTF7HfptJxiBjz0/yM+9MDKPlIyel+XCaFbPw5BNuNCfn6FYsghjkGHDGPqs0tFQlo2XqM5ht9OoZa29/XGAprf/Z61iNRVXhqBjq1r1vnsZmhkL729G3cowNcppsFYbsRUa9a5QJ7k1CgfkHZy1waSgCcuyNmSVja48fcD4+hUaTob+cIdb4vZ7aWPdRQADRdYmIJ4IcwM'
!db 'w75gbi7lyvYptCYXbJi54aqXH1X6C2KeURmOduOXnzN+zWAltSK3ON/kAxGh2m6gQQVFXfR2i5gd/wIGnRyFIc84ufAOM6i4d2BVik1aL60jL1X0ykdwHpcV3KeoVVgdBBSae+Vcyzz/i71AvvkgTZa9YJwE5fQgUYhvrhbJXNSy8MHfbr4XpKetPlLhfTvD7yOsFyhAdcp2tjrYTSEMfaT3M7QLiN4In6+wF1ADwXKtdhjrRULuy1moJ/AMCNEO'
!db '+w/RULVNngiuEBHncqzejGHIZhGTz7FXqG8+XvMhOS33y4s346OmqMlNKknMFt72i+nZRtThYrlXwD3HjX1ko/n0XVrujxZwfsYDCfDu1vFGZurfxTdWHu3ytpHRPWeTW8l7pv2tUU61SEzUZIhGHtdzgW/+PQNMs03w68lMu+JgIL8Ebi3rU/QiiV6oabEdIzOj9jtNgb663xA8dqBaTGmLQFh4rd5Xfv4lfLx0vdhirKu+nmfNc6Gjd/3FfYJk'
!db 'NplHj3nmZI7LDCO+/y7BAjgBym+yuWVjZCfQ7OvVVhzI8g0PjtMp7BVzIFYwXPaA5F1Cia7tB4eJR7O+lVeuedPo9PXJWIybvH350qZ07sZQY1Euc1Vy/N/KCB8f/1sZIW5adKjrXtH1ZIJB20i6u9Wj2x7qvb5Gy3lU/RoB1bizIIt+Dee6gB62Yt0GY+2V1PzUkbfV3HOfXS2qdPPgEuM+np0Pj9ILHA+HzHDdvP4q8RWPXy/7sf4VXyXyT5xN'
!db 'EqWrZFpUIx1Y/AO1TNGp1RKQ0N9ChxqQbA1oWPidx56Jjc0xrtsQRad8T8hd/k89oel7l72ZmX/0cY5n+VjFw7lBSaKA7ur2JjNb2LyavaALxPA5SCaxQYNbx0NjzokQvQSsZ4b+haJk/tsZ8eTUTUaagdwNfxQDw3gUHtt3q6a1c3dFi+4xecNWvnwo9HypDfwPIhtbWKAc+xb79Q0JyfEN6k/fnGSbudHs0z+6t8Fo3UlLzqurqw8ADOwPxF/Q'
!db 'uCLtb/C1/eQPCPsPc3z3KTI3Ac/Khb3n/9QCAiiWB5yH+ar27wNu3B0fvX8m/jBODHML70AkRpw3UGxI6BmgK+YC40j6dTamuBYfrWusZos9idjp3qZi34ufmTiZ4cEpJl4zv+n9+IbwlJ27hb0PwxmeP3hwpH73x0/9J39+viTRDTopTF42SSpEg3aERW5cAg1Opj1Dp+VAwuc/HpGVVJIoE/v85X8ASP/4ag=='
E:
EndDataSection
JHPJHP
Addict
Addict
Posts: 2129
Joined: Sat Oct 09, 2010 3:47 am
Contact:

Re: Analyzing special font files

Post by JHPJHP »

Hi Michael Vogel,

Have you read the following: https://developer.garmin.com/connect-iq ... ge-layout/
developer.garmin.com wrote:Text Fonts Versus Number Fonts
Garmin devices have two kinds of fonts available — text fonts and number fonts[1]. Text fonts are for displaying text and numbers and come in three sizes
...
In addition, have tried using their suggested tool: http://www.angelcode.com/products/bmfont/
developer.garmin.com wrote:User Fonts
Garmin tries to provide the best looking fonts for the device. Using the BMFont tool, you can import your own typeface into the product. Using the BMFont tool, you can import truetype font into a font usable by Connect IQ. There are some guidelines to follow:
...
User avatar
Michael Vogel
Addict
Addict
Posts: 2680
Joined: Thu Feb 09, 2006 11:27 pm
Contact:

Re: Analyzing special font files

Post by Michael Vogel »

Thanks, yes I know these things...

...the main problem with the fonts (text and numbers) is that they are completely different in size, weight and design for different Garmin devices. This makes it a little bit difficult to create programs looking cool on multiple platforms.

With the Bmfont tool you generate a standard bitmap and a text file from a true type font. I wrote a tool which allows to view this type of "user font".

As soon such a user font is added to a program as a resource, it seems to get compressed - and the compression method looks identical like seen in "monkeyface fonts" which are used for a simulator.

So why I'd like to decode this? There are a lot of reasons: one is, to be able to view/compare all fonts in the SDK. Knowing the compression algorithm would also allow to optimize self made fonts, because the programs need to be small because of the limited memory on certain Garmin devices.
User avatar
Mijikai
Addict
Addict
Posts: 1360
Joined: Sun Sep 11, 2016 2:17 pm

Re: Analyzing special font files

Post by Mijikai »

Can you upload a monkeyface font file?
User avatar
Michael Vogel
Addict
Addict
Posts: 2680
Joined: Thu Feb 09, 2006 11:27 pm
Contact:

Re: Analyzing special font files

Post by Michael Vogel »

Maybe you'd like to download the SDK here, no matter if you select 3.0.11 or the newer beta release. Both versions do have around 200 fonts in a zip file, so no installation is needed.

As I have seen so far, each font starts with a header like this:
4 Bytes Magic Number or Version: $0,$24,$3,$6
4 Bytes File size
4 Bytes Pointer to Table1
4 Bytes Pointer to Table2
4 Bytes Pointer to Bitmap Data
next 12 Bytes are unsure so far (maybe the character size in the second long value)
4 Bytes Magic Number $12345678
Continued by Table1, Table2 and the Bitmap Data
User avatar
Mijikai
Addict
Addict
Posts: 1360
Joined: Sun Sep 11, 2016 2:17 pm

Re: Analyzing special font files

Post by Mijikai »

Michael Vogel wrote: next 12 Bytes are unsure so far (maybe the character size in the second long value)
4 Bytes Magic Number $12345678
H...m i dont get any number that would indicate the charachter dimensions :S
How to make sense of the bitmap data without a dimension...

Code: Select all

fnt: FNT_NOTO_SANS_CJK_KR_BOLD_40.monkeyface

fntMagic:  2360070 / 0x240306
fntSize:   2541979

unkTable1: 36
unkTable2: 40600
fntBits:   109108

unkTable1_size:  40564
unkTable2_size:  68508
fntBits_size:    2432871

unknown values (dimension)

unk1 (dword): 2147418152 / 0x7FFF0028
unk2 (dword): 2031627 / 0x1F000B 
unk3 (dword): 1 / 0x1
marker: 305419896 / 0x12345678
User avatar
Michael Vogel
Addict
Addict
Posts: 2680
Joined: Thu Feb 09, 2006 11:27 pm
Contact:

Re: Analyzing special font files

Post by Michael Vogel »

You're right, it's quite tricky (because I couldn't find even a small fragment of documentation somewhere)...

There are some possibilities where the glyph sizes are defined: globally in the main header (named XY in the structure) or seperately for each character (so what about the data in table1 and table2?)

Table #1 is completely strange - no idea what it is good for?! Also strange that table1 has a different number of entries than table2 has. And where are the ASCII or Unicode codes to know if the bitmaps shows an "A" or "B" or whatever?

Table #2 seems to have more info in each 4 byte entry (I name it 11 22 33 44 for a while) than just the offset to the font bits, I can imagine that the offset is taken from the reversed byte order 44 33 22 11 (and maybe only 20 bits of them). That means this offset (which is needed to be added to the font bit offset from the header) uses the following part of the 4 bytes: 11 22 -3 --. No idea if this is correct and what the other 12 bits (-- -- 3- 44) would be used for.

The following code just read the font header and show the content of one of the tables.

Code: Select all

#File="Fontfilename"

; Define

	Structure MonkeyFaceHeader
		Magic.l
		Size.l
		Tab1.l
		Tab2.l
		ImageData.l
		ImageSize.l
		XY.l
		One.l
		One_Eight.l
		;
		Tab1Entries.i
		Tab2Entries.i
	EndStructure

	Global FontHeader.MonkeyFaceHeader
	Global *Buffer

	Global Dim Tab1.l(0)
	Global Dim Tab2.l(0)
	Global Dim Tab3.l(0)

	Macro Long(Mem)
		((PeekA(Mem)<<24) | (PeekA(Mem+1)<<16) | (PeekA(Mem+2)<<8) | (PeekA(Mem+3)) )
	EndMacro

; EndDefine
Procedure ShowTab(mem.i)

	Protected i
	Protected header.i
	Protected size.i
	Protected *Mem

	*Mem=*Buffer+mem
	header=Long(*Mem) : *Mem+4
	size=Long(*Mem) : *Mem+4

	With FontHeader
		If \Tab1+size=\Tab2
			\Tab1Entries=size/4-2

			ReDim Tab1(\Tab1Entries)
			For i=1 To \Tab1Entries
				Tab1(i)=Long(*Mem)
				Debug Str(i)+": "+RSet(Hex(Tab1(i)),4,"0")+", "+Hex(*mem-*Buffer)
				*Mem+4
			Next i
		EndIf

	EndWith


EndProcedure
Procedure main()

	Protected *Mem
	Protected *Val

	size=FileSize(#File)
	If size>0 And ReadFile(0,#File)
		*Buffer=AllocateMemory(size)
		If *Buffer
			If ReadData(0,*Buffer,size)=size
				With FontHeader
					*Mem=*Buffer
					*Val=@FontHeader
					For i=0 To 9
						PokeL(*Val,Long(*Mem)); entspricht \Magic=PeekL(*Buffer) bis \Unknown5=PeekL(*Buffer+9*4)
						*Val+4
						*Mem+4
					Next i
					If \Size=size
						Debug "ok"
						Debug \Tab1
						Debug \Tab2
						Debug \ImageData
						ShowTab(\Tab1)
					EndIf
				EndWith
			EndIf
		EndIf
	EndIf

EndProcedure

main()
Post Reply