· 6 years ago · Apr 04, 2019, 09:16 PM
1'Coded by UEZ build 2019-03-30
2'Thanks to marpon for simple_lzfx_v2
3'Windows only!
4
5#Include Once "fbgfx.bi"
6#Include Once "file.bi"
7#Include Once "windows.bi"
8#Include Once "win\ShellApi.bi"
9#Include Once "win\Shlwapi.bi"
10#Include Once "win\commdlg.bi"
11#Include Once "zlib.bi"
12#Include Once "TitchySID v2.bi"
13
14#Ifdef __Fb_64bit__
15 #Inclib "Gdiplus"
16 #Include Once "win\gdiplus-c.bi"
17#Else
18 #Include Once "win\gdiplus.bi"
19 Using Gdiplus
20#Endif
21
22Using FB
23
24Dim As OSVERSIONINFO OS
25OS.dwOSVersionInfoSize = Sizeof(OS)
26GetVersionEx(@OS)
27
28If OS.dwBuildNumber < 7600 Then
29 MessageBox(0, "This operating system is not supported (Win7+ only)!", "ERROR", MB_OK Or MB_ICONSTOP Or MB_TOPMOST)
30 End
31Endif
32
33#Define CRLF (Chr(13, 10))
34
35'init GDIPlus
36Dim gdipToken As ULONG_PTR
37Dim GDIp As GdiplusStartupInput
38GDIp.GdiplusVersion = 1
39If GdiplusStartup(@gdipToken, @GDIp, NULL) <> 0 Then End
40
41Type tFileArray
42 As Wstring * 4096 files(Any)
43End Type
44
45Declare Sub About(fDAngle As Single = 180)
46Declare Function FileSaveDialog (Byref sTitle As String, Byref sDir As String = CurDir, sFilter As String = !"All Files (*.*)" + Chr(0) + "*.*" + Chr(0, 0)) As String
47Declare Sub BaseEncoder(aFiles As tFileArray, iLineLen As Ushort = 992)
48Declare Function WndProc(hWnd As HWND,uMsg As UINT,wParam As WPARAM,lParam As LPARAM) As Integer
49Declare Function _WinAPI_IniRead(sIniFile As String, sSection As String, sKey As String, sDefault As String = "default") As String
50Declare Function _WinAPI_IniWrite(sIniFile As String, sSection As String, sKey As String, sValue As String = "default") As Integer
51Declare Function _WinAPI_CreateToolTip(hDlg As HWND, sToolTipText As String, bBalloon As Ubyte = 1, iWidth As Ushort = 500, toolID As Integer = 0) As HWND
52Declare Function _WinAPI_FlashWindowEx(hWND As HWND, iFlag As DWORD = FLASHW_ALL, iCount As ULong = 10, iTimeOut As DWORD = 500) As Integer
53Declare Function _WinAPI_RtlCompress(pBinary As Ubyte Ptr, iBinarySize As Ulong, Byref iCompressedSize As Ulong, bMaxCompression As Ubyte = 1, iCompressionEngine As Ushort = COMPRESSION_FORMAT_LZNT1) As Ubyte Ptr
54Declare Function _WinAPI_RtlDecompress(aBinary As Ubyte Ptr, iFileSize As Ulong, iCompressedSize As Ulong, iDecompressionEngine As Ushort = COMPRESSION_FORMAT_LZNT1) As Ubyte Ptr
55Declare Sub _WinAPI_InsertMenuItem(hMenuMain As HMENU, iItem As Uinteger, sText As String, iID As Uinteger = 0, hSubMenu As HMENU = 0, hBitmap As Any Ptr = 0, iBGColor As Integer = COLOR_HIGHLIGHTTEXT)
56Declare Function DecompressBGImage() As Any Ptr
57Declare Function _GDIPlus_BitmapCreateFromMemory3(aBinImage As Ubyte Ptr, iLen As Ulong, bBitmap_GDI As Bool = False) As Any Ptr
58Declare Function _WinAPI_Base64Encode(binArray As Ubyte Ptr, iLen As Ulong, Byref iB64Len As Ulong, iFLags As Ulong = (CRYPT_STRING_BASE64 Or CRYPT_STRING_NOCRLF)) As String
59Declare Function Base91Decode(sString As String, Byref iBase91Len As Ulong) As Ubyte Ptr
60Declare Function Base91Encode(binArray As Ubyte Ptr, iLen as ulong, ByRef iLenOut as Ulong) As String
61Declare Function Base128Encode(binArray As Ubyte Ptr, iLen as ulong, ByRef iLenOut as Ulong) As String
62Declare Function DecompressBaseImage() As any Ptr
63Declare Function DecompressCompressImage() As Any Ptr
64Declare Function DecompressOutputImage() As Any Ptr
65Declare Function DecompressExitImage() As Any Ptr
66Declare Function DecompressAboutImage() As Any Ptr
67Declare Function DecompressHorseAnim() As Any Ptr
68Declare Function DecompressResetImage() As Any Ptr
69Declare Function DecompressFBIcnImage() As Any Ptr
70Declare Sub DecompressSID()
71
72'Simple lzfx encoder - decoder without dependancies @ https://www.freebasic.net/forum/viewtopic.php?f=7&t=27188#p254954
73Declare Function lzfx_compress(Byval ibuf As Ubyte Ptr , Byval ilen As Ulong , Byval obuf As Ubyte Ptr , Byref olen As Ulong) As Long
74Declare Function size_comp_buffer(Byval ibuf As Ubyte Ptr , Byval ilen As Ulong ) As Long
75
76/' Hashtable size (2**LZFX_HLOG entries) '/
77#Ifndef LZFX_HLOG
78 # define LZFX_HLOG 16
79#Endif
80
81/' Predefined errors. '/
82#Define LZFX_ESIZE -1 /' Output buffer too small '/
83#Define LZFX_ECORRUPT -2 /' Invalid Data for decompression '/
84#Define LZFX_EARGS -3 /' Arguments invalid (NULL) '/
85
86
87#Define LZFX_HSIZE (1 Shl (LZFX_HLOG))
88
89/' Define the hash Function '/
90#Define LZFX_FRST(p) (((p[0]) Shl 8) Or p[1])
91#Define LZFX_NEXT(v,p) (((v) Shl 8) Or p[2])
92#Define LZFX_IDX(h) ((( h Shr (3 * 8 - LZFX_HLOG)) - h ) And (LZFX_HSIZE - 1))
93
94/' These cannot be changed, as they are related to the compressed Format. '/
95#Define LZFX_MAX_LIT (1 Shl 5)
96#Define LZFX_MAX_OFF (1 Shl 13)
97#Define LZFX_MAX_REF ((1 Shl 8) + (1 Shl 3))
98
99/' This macro to reproduce !a in c'/
100#Define MY_NOT(value) Iif(value = 0, 1, 0)
101
102
103Const SC_DRAGMOVE = &hF012, iMaxFilesizeSum = 100 * 1024^2 '100 MB
104Const fPI = Acos(-1), fRad = Acos(-1) / 180, fDeg = 180 / Acos(-1)
105
106Dim As WNDCLASSEX wc
107Dim As MSG msg
108Dim Shared As HWND hGUI, hPic, hProgressbar
109Dim As Integer sW, sH
110ScreenInfo(sW, sH)
111
112Dim szAppName As ZString * 6 => "FB GUI"
113Dim Shared As String sTitle
114sTitle = "FB File2Bas Code Generator v0.99 build 2019-03-30 beta"
115
116Dim Shared As UShort iW, iH
117iW = 160
118iH = 120
119
120Dim Shared As Short iDefaultPosX, iDefaultPosY
121iDefaultPosX = (sW - iW) \ 2
122iDefaultPosY = (sH - iH) \ 2
123Dim Shared As Ubyte iBaseEncoder = 2, iCompression, bOutputFile, bOutputClipboard, bMaxCompression, bProbeAllCompressors
124iCompression = 5: bOutputFile = 1: bOutputClipboard = 0: bMaxCompression = 1: bProbeAllCompressors = 0
125Dim As Short xPos = CShort(_WinAPI_IniRead(Exepath & "\FB File2Bas Code Generator.ini", "GUI", "x", Str(iDefaultPosX)))
126Dim As Short yPos = Cshort(_WinAPI_IniRead(Exepath & "\FB File2Bas Code Generator.ini", "GUI", "y", Str(iDefaultPosY)))
127iBaseEncoder = Cubyte(_WinAPI_IniRead(Exepath & "\FB File2Bas Code Generator.ini", "Base", "Encoder", Str(iBaseEncoder)))
128iCompression = Cubyte(_WinAPI_IniRead(Exepath & "\FB File2Bas Code Generator.ini", "Compression", "Engine", Str(iCompression)))
129bMaxCompression = Cubyte(_WinAPI_IniRead(Exepath & "\FB File2Bas Code Generator.ini", "Compression", "MaxCompression", Str(bMaxCompression)))
130bProbeAllCompressors = Cubyte(_WinAPI_IniRead(Exepath & "\FB File2Bas Code Generator.ini", "Compression", "ProbeAllCompressors", Str(bProbeAllCompressors)))
131bOutputFile = CUbyte(_WinAPI_IniRead(Exepath & "\FB File2Bas Code Generator.ini", "Output", "File", Str(bOutputFile)))
132bOutputClipboard = CUbyte(_WinAPI_IniRead(Exepath & "\FB File2Bas Code Generator.ini", "Output", "Clipboard", Str(bOutputClipboard)))
133
134iBaseEncoder = Iif(iBaseEncoder < 0, 0, Iif(iBaseEncoder > 2, 2, iBaseEncoder))
135iCompression = Iif(iCompression < 0, 0, Iif(iCompression > 5, 5, iCompression))
136
137Dim Shared As String aBaseEncoder(2)
138aBaseEncoder(0) = "Base64"
139aBaseEncoder(1) = "Base91"
140aBaseEncoder(2) = "Base128"
141
142Dim Shared As tFileArray aFiles
143Dim Shared As RECT tPos
144Dim Shared As Ubyte bFilesAdded = 0
145Dim Shared As Ushort iFilesAdded = 0
146
147With wc
148 .style = CS_HREDRAW Or CS_VREDRAW
149 .lpfnWndProc = @WndProc
150 .cbClsExtra = NULL
151 .cbWndExtra = NULL
152 .hInstance = GetModuleHandle(NULL)
153 .hIcon = LoadIcon(.hInstance, "FB_PROGRAM_ICON")
154 .hCursor = LoadCursor(NULL, IDC_ARROW)
155 .hbrBackground = GetStockObject(WHITE_BRUSH)
156 .lpszMenuName = NULL
157 .lpszClassName = @szAppName
158 .cbSize = SizeOf(WNDCLASSEX)
159End With
160
161RegisterClassEx(@wc)
162
163hGUI = CreateWindowEx( WS_EX_TOPMOST Or WS_EX_ACCEPTFILES, _
164 wc.lpszClassName, _
165 sTitle, _
166 WS_VISIBLE Or WS_POPUPWINDOW, _
167 xPos, yPos, _
168 iW, iH, _
169 NULL, NULL, wc.hInstance, NULL)
170
171
172Dim As HWND hTooltip = _WinAPI_CreateToolTip(hGUI, "Drag'n'drop files here to convert to any base format (folders will be ignored!)!" & CRLF & "Rmb to display settings menu.")
173
174hPic = CreateWindowEx(NULL, "Static", "", SS_BITMAP Or WS_CHILD Or WS_VISIBLE, 0, 0, iW, iH, hGUI, NULL, NULL, NULL)
175Dim As HBITMAP hLogo = DecompressBGImage()
176SendMessage(hPic, STM_SETIMAGE, IMAGE_BITMAP, Cast(LPARAM, hLogo))
177
178Dim As RECT rcClient
179GetClientRect(hGUI, @rcClient)
180
181Dim As Integer cyVScroll = GetSystemMetrics(SM_CYVSCROLL)
182
183hProgressbar = CreateWindowEx( 0, PROGRESS_CLASS, NULL, _
184 WS_CHILD or WS_VISIBLE Or PBS_SMOOTH, _
185 rcClient.left, rcClient.bottom - 10, _
186 rcClient.right, cyVScroll, _
187 hGUI, 0, wc.hInstance, NULL)
188
189SendMessage(hProgressbar, PBM_SETSTEP, 1, 0)
190SendMessage(hProgressbar, PBM_SETBARCOLOR, 0, Cast(LPARAM, &hFFFFFF)) 'BGR
191SendMessage(hProgressbar, PBM_SETBKCOLOR, 0, Cast(LPARAM, &h0)) 'BGR
192
193ShowWindow(hGUI, SW_NORMAL)
194
195
196Const WM_SHELLNOTIFY = WM_USER + 5, id_EncoderB91 = 5000, id_EncoderB128 = 5001, id_EncoderB64 = 5002, _
197 id_OutputFile = 5100, id_OutputClipboard = 5101, _
198 id_About = 5200, id_Exit = 5300, _
199 id_CompressionDisabled = 5400, id_CompressionLZNT1 = 5401, id_CompressionXPRESS = 5402, id_CompressionXPRESSHUFF = 5403, id_CompressionLZFX = 5405, id_CompressionZLib = 5406, _
200 id_CompressionMaxCompression = 5450, id_ProbeAllCompressors = 5460, _
201 id_TrayReset = 5500, id_TrayExit = 5501, id_TrayAbout = 5502
202Dim Shared As HANDLE hMenuMain, hMenuSub1, hMenuSub2, hMenuSub3
203
204Dim As HBITMAP hBmpCompress = DecompressCompressImage(), hBmpOutput = DecompressOutputImage(), hBmpAbout = DecompressAboutImage(), hBmpExit = DecompressExitImage(), _
205 hBmpBase = DecompressBaseImage(), hBmpReset = DecompressResetImage(), hBmpFBIcn = DecompressFBIcnImage()
206
207'create popup menu
208hMenuMain = CreatePopupMenu()
209hMenuSub1 = CreatePopupMenu()
210hMenuSub2 = CreatePopupMenu()
211hMenuSub3 = CreatePopupMenu()
212
213_WinAPI_InsertMenuItem(hMenuMain, 0, "Base encoder", 0, hMenuSub1, hBmpBase)
214_WinAPI_InsertMenuItem(hMenuMain, 1, "Compression", 0, hMenuSub2, hBmpCompress)
215_WinAPI_InsertMenuItem(hMenuMain, 2, "Output to", 0, hMenuSub3, hBmpOutput)
216_WinAPI_InsertMenuItem(hMenuMain, 3, "")
217_WinAPI_InsertMenuItem(hMenuMain, 4, "About", id_About, , hBmpAbout)
218_WinAPI_InsertMenuItem(hMenuMain, 5, "")
219_WinAPI_InsertMenuItem(hMenuMain, 6, "Exit", id_Exit, , hBmpExit)
220
221_WinAPI_InsertMenuItem(hMenuSub1, 0, aBaseEncoder(0), id_EncoderB64)
222_WinAPI_InsertMenuItem(hMenuSub1, 1, aBaseEncoder(1), id_EncoderB91)
223_WinAPI_InsertMenuItem(hMenuSub1, 2, aBaseEncoder(2), id_EncoderB128)
224CheckMenuRadioItem(hMenuSub1, 0, 2, iBaseEncoder, MF_BYPOSITION)
225
226_WinAPI_InsertMenuItem(hMenuSub2, 0, "Disabled", id_CompressionDisabled)
227_WinAPI_InsertMenuItem(hMenuSub2, 1, "LZNT (Windows build-in) (default)", id_CompressionLZNT1)
228_WinAPI_InsertMenuItem(hMenuSub2, 2, "XPRESS (Windows build-in)", id_CompressionXPRESS) 'available on Win8+ os
229_WinAPI_InsertMenuItem(hMenuSub2, 3, "XPRESS HUFFmann (Windows build-in)", id_CompressionXPRESSHUFF) 'available on Win8+ os
230_WinAPI_InsertMenuItem(hMenuSub2, 4, "LZFX (experimental)", id_CompressionLZFX)
231_WinAPI_InsertMenuItem(hMenuSub2, 5, "ZLib", id_CompressionZLib)
232Dim Shared As Ubyte iMaxMenuSub2Items = 5
233_WinAPI_InsertMenuItem(hMenuSub2, iMaxMenuSub2Items + 1, "")
234_WinAPI_InsertMenuItem(hMenuSub2, iMaxMenuSub2Items + 2, "Use max compression", id_CompressionMaxCompression)
235_WinAPI_InsertMenuItem(hMenuSub2, iMaxMenuSub2Items + 3, "")
236_WinAPI_InsertMenuItem(hMenuSub2, iMaxMenuSub2Items + 4, "Probe all compressors (might be slow!)", id_ProbeAllCompressors)
237
238_WinAPI_InsertMenuItem(hMenuSub3, 0, "File", id_OutputFile)
239_WinAPI_InsertMenuItem(hMenuSub3, 1, "Clipboard", id_OutputClipboard)
240
241If OS.dwBuildNumber < 9200 Then
242 EnableMenuItem(hMenuSub2, id_CompressionXPRESS, MF_DISABLED or MF_GRAYED)
243 EnableMenuItem(hMenuSub2, id_CompressionXPRESSHUFF, MF_DISABLED or MF_GRAYED)
244 If iCompression = 2 Or iCompression = 3 Then iCompression = 1
245End If
246
247'Region Tray Menu
248Dim Shared As HMENU TrayMenu, MainMenu
249MainMenu = CreateMenu()
250TrayMenu = CreateMenu()
251Dim Shared As NOTIFYICONDATA SystrayIcon
252
253'Dim HICON As hIcon = ExtractIcon(GetModuleHandle(0), Command(0), 0)
254Dim As ICONINFO tIcon
255tIcon.fIcon = True
256tIcon.fIcon = True
257tIcon.hbmMask = hBmpFBIcn
258tIcon.hbmColor = hBmpFBIcn
259Dim HICON As hIcon = CreateIconIndirect(@tIcon)
260
261With SystrayIcon
262 .cbSize = Len(SystrayIcon)
263 .hWnd = hGUI
264 .uId = 1&
265 .uFlags = NIF_ICON Or NIF_TIP Or NIF_MESSAGE
266 .uCallbackMessage = WM_SHELLNOTIFY
267 .hIcon = hIcon
268 .szTip = sTitle + Chr(0)
269End With
270
271AppendMenu(TrayMenu, MF_STRING, id_TrayReset, "&Reset Windows Position")
272AppendMenu(TrayMenu, MF_SEPARATOR, 0, 0)
273AppendMenu(TrayMenu, MF_STRING, id_TrayAbout, "&About")
274AppendMenu(TrayMenu, MF_SEPARATOR, 0, 0)
275AppendMenu(TrayMenu, MF_STRING, id_TrayExit, "&Exit")
276InsertMenu(MainMenu, 0, MF_POPUP, Cptr(UINT_PTR, TrayMenu), 0)
277
278SetMenuItemBitmaps(TrayMenu, id_TrayReset, MF_BYCOMMAND, hBmpReset, hBmpReset)
279SetMenuItemBitmaps(TrayMenu, id_TrayAbout, MF_BYCOMMAND, hBmpAbout, hBmpAbout)
280SetMenuItemBitmaps(TrayMenu, id_TrayExit, MF_BYCOMMAND, hBmpExit, hBmpExit)
281
282Shell_NotifyIcon(NIM_ADD, @SystrayIcon)
283
284Dim As MENUINFO tMenuBgColor
285With tMenuBgColor
286 .cbSize = Sizeof(MENUINFO)
287 .fMask = MIM_BACKGROUND
288 .hbrBack = GetSysColorBrush(COLOR_HIGHLIGHTTEXT)
289End With
290SetMenuInfo(TrayMenu, Cast(LPCMENUINFO, @tMenuBgColor))
291
292
293iCompression = Iif(iCompression < 0, 0, Iif(iCompression > iMaxMenuSub2Items, iMaxMenuSub2Items, iCompression))
294Select Case iCompression
295 Case 0 'no compression
296 CheckMenuRadioItem(hMenuSub2, 0, iMaxMenuSub2Items, iCompression, MF_BYPOSITION)
297 Case 1 'COMPRESSION_FORMAT_LZNT1
298 CheckMenuRadioItem(hMenuSub2, 0, iMaxMenuSub2Items, iCompression, MF_BYPOSITION)
299 Case 2 'COMPRESSION_FORMAT_XPRESS
300 CheckMenuRadioItem(hMenuSub2, 0, iMaxMenuSub2Items, iCompression, MF_BYPOSITION)
301 Case 3 'COMPRESSION_FORMAT_XPRESS_HUFF
302 CheckMenuRadioItem(hMenuSub2, 0, iMaxMenuSub2Items, iCompression, MF_BYPOSITION)
303 Case 4 'internal LZFX compression format
304 CheckMenuRadioItem(hMenuSub2, 0, iMaxMenuSub2Items, iCompression, MF_BYPOSITION)
305 Case 5 'ZLib compression format
306 CheckMenuRadioItem(hMenuSub2, 0, iMaxMenuSub2Items, iCompression, MF_BYPOSITION)
307End Select
308
309If bOutputFile Then CheckMenuItem(hMenuSub3, id_OutputFile, MF_CHECKED)
310If bOutputClipboard Then CheckMenuItem(hMenuSub3, id_OutputClipboard, MF_CHECKED)
311If bMaxCompression Then CheckMenuItem(hMenuSub2, id_CompressionMaxCompression, MF_CHECKED)
312If bProbeAllCompressors Then
313 CheckMenuItem(hMenuSub2, id_ProbeAllCompressors, MF_CHECKED)
314 EnableMenuItem(hMenuSub2, id_CompressionDisabled, MF_DISABLED or MF_GRAYED)
315 EnableMenuItem(hMenuSub2, id_CompressionLZNT1, MF_DISABLED or MF_GRAYED)
316 EnableMenuItem(hMenuSub2, id_CompressionXPRESS, MF_DISABLED or MF_GRAYED)
317 EnableMenuItem(hMenuSub2, id_CompressionXPRESSHUFF, MF_DISABLED or MF_GRAYED)
318 EnableMenuItem(hMenuSub2, id_CompressionLZFX, MF_DISABLED or MF_GRAYED)
319 EnableMenuItem(hMenuSub2, id_CompressionZLib, MF_DISABLED or MF_GRAYED)
320Endif
321If iCompression = 0 Then EnableMenuItem(hMenuSub2, id_ProbeAllCompressors, MF_DISABLED or MF_GRAYED)
322
323
324Dim Shared As HCURSOR hAnim
325hAnim = DecompressHorseAnim()
326
327While GetMessage(@msg, 0, 0, 0)
328 TranslateMessage(@msg)
329 DispatchMessage(@msg)
330 'If InKey = Chr(27) Then Exit While
331Wend
332
333Shell_NotifyIcon(NIM_DELETE, @SystrayIcon)
334DestroyIcon(hIcon)
335DestroyCursor(hAnim)
336DeleteObject(hLogo)
337DeleteObject(DecompressBaseImage)
338DeleteObject(hBmpCompress)
339DeleteObject(hBmpOutput)
340DeleteObject(hBmpExit)
341DeleteObject(hBmpAbout)
342DeleteObject(hBmpReset)
343DeleteObject(hBmpFBIcn)
344
345GdiplusShutdown(gdipToken)
346
347_WinAPI_IniWrite(Exepath & "\FB File2Bas Code Generator.ini", "GUI", "x", Str(tPos.Left))
348_WinAPI_IniWrite(Exepath & "\FB File2Bas Code Generator.ini", "GUI", "y", Str(tPos.Top))
349_WinAPI_IniWrite(Exepath & "\FB File2Bas Code Generator.ini", "Base", "Encoder", Str(iBaseEncoder))
350_WinAPI_IniWrite(Exepath & "\FB File2Bas Code Generator.ini", "Compression", "Engine", Str(iCompression))
351_WinAPI_IniWrite(Exepath & "\FB File2Bas Code Generator.ini", "Compression", "MaxCompression", Str(bMaxCompression))
352_WinAPI_IniWrite(Exepath & "\FB File2Bas Code Generator.ini", "Compression", "ProbeAllCompressors", Str(bProbeAllCompressors))
353_WinAPI_IniWrite(Exepath & "\FB File2Bas Code Generator.ini", "Output", "File", Str(bOutputFile))
354_WinAPI_IniWrite(Exepath & "\FB File2Bas Code Generator.ini", "Output", "Clipboard", Str(bOutputClipboard))
355
356End
357
358Private Sub About(fDAngle As Single = 180)
359 If Fileexists(Curdir & "\Unicornflakes.sid") <> -1 Then DecompressSID()
360
361 Dim As __tagSIDInfo SID
362 Dim As __TitchySID TitchySID
363 TitchySID.Open(Curdir & "\Unicornflakes.sid", 0)
364
365 Dim As UShort iW = 600, iH = 600, fCx = iW \ 2, fCy = iH \ 2
366 Dim As String sText = " " & sTitle & " coded by UEZ. Thanks to marpon for simple_lzfx_v2, StatMat for TitchySID.dll, Soren Lund for the SID and JL Gaillly / M. Adler for zlib. Press ESC or close window to exit ..............."
367 Dim As Ushort iLen = Len(sText)
368 Dim as Short i
369 Dim As String aText(0 To iLen - 1)
370 For i = 0 To iLen - 1
371 aText(i) = Mid(sText, iLen - i, 1)
372 Next
373 Type tagChars
374 As Single x, y
375 As Any Ptr img, gfx
376 End Type
377 Dim As tagChars tCoord(iLen - 1)
378 Dim As Single fSize = iLen / Sqr((iW * iW) + (iH * iH)) * 512, fSize2 = fSize * 2
379 Dim As Single fDegree, fAngle, mwx, mwy, fFontSize, f1, f2, c1 = fSize / 2, c2 = fSize2 / 2, fRadius = Sqr((iW * iW) / 10 + (iH * iH) / 10), _
380 iDX = -fSize / 2, iDY = iDX, c3, c4 = iLen / 6, c5 = 0.85 * Sqr((iW * iW) / 2 + (iH * iH) / 2) / 2, _
381 c6 = (iH / iW), c7 = (iW / iH)
382
383 ScreenControl SET_DRIVER_NAME, "GDI"
384 ScreenRes iW, iH, 32, 1, GFX_HIGH_PRIORITY Or GFX_NO_SWITCH Or GFX_ALWAYS_ON_TOP Or GFX_HIGH_PRIORITY Or &h80000000
385 WindowTitle "About"
386
387 'center windows by adding the taskbar to the calculation
388 Dim as Integer iDW, iDH
389 ScreenControl GET_DESKTOP_SIZE, iDW, iDH
390 Dim tWorkingArea As RECT
391 SystemParametersInfo(SPI_GETWORKAREA, null, @tWorkingArea, null)
392 ScreenControl SET_WINDOW_POS, (iDW - iW) \ 2, ((tWorkingArea.Bottom - iH) - (iDH - tWorkingArea.Bottom)) \ 2
393
394 Dim as HWND hHWND
395 ScreenControl(GET_WINDOW_HANDLE, Cast(Integer, hHWND))
396
397 'init GDI / GDI+ canvas, pens, brushes, etc. for drawing
398 Dim As BITMAPINFO tBITMAP
399 With tBITMAP.bmiheader
400 .biSize = Sizeof(BITMAPINFOHEADER)
401 .biWidth = iW
402 .biHeight = -iH
403 .biPlanes = 1
404 .biBitCount = 32
405 .biCompression = BI_RGB
406 End With
407
408 Dim As GpRectF tLayout, tLayout2
409 tLayout2.x = 0
410 tLayout2.y = 0
411 tLayout2.width = fSize
412 tLayout2.height = fSize / 2
413 Dim As Ulong Ptr aBitmap
414 Dim As Any Ptr hDC = GetDC(hHWND), _
415 hHBitmap = CreateDIBSection(hDC, @tBITMAP, DIB_RGB_COLORS, @aBitmap, NULL, NULL), _
416 hDC_backbuffer = CreateCompatibleDC(hDC), _
417 hObjOld, hCanvas, hPen, hPen2, hBrush, hBrush2, hBrush_c, hMatrix, hMatrix2, hFont, hFamily, hFormat, hBitmap, hGfx, _
418 hBitmap_Cursor, hGfx_Cursor, hBitmap_Bg, hGfx_Bg, hPath
419
420 hObjOld = SelectObject(hDC_backbuffer, hHBitmap)
421 GdipCreateFromHDC(hDC_backbuffer, @hCanvas)
422 GdipSetSmoothingMode(hCanvas, 6) '6 = 8x8 aa
423 GdipSetPixelOffsetMode(hCanvas, PixelOffsetModeHalf)
424 'GdipSetInterpolationMode(hCanvas, InterpolationModeHighQualityBicubic)
425 GdipSetCompositingQuality(hCanvas, CompositingQualityGammaCorrected)
426 GdipGraphicsClear(hCanvas, &hFF606E8C)
427
428 GdipCreatePen1(&h28101010, 1, 2, @hPen)
429 GdipSetPenStartCap(hPen, &h14)
430
431 GdipCreatePen1(&h78101010, 8, 2, @hPen2)
432 GdipCreateLineBrushFromRectWithAngle(@tLayout2, &hD0202080, &hF06060FF, 45, 1, 0, @hBrush)
433 GdipSetLineSigmaBlend(hBrush, 0.5, 0.95)
434
435
436 GdipCreateBitmapFromScan0(iW, iH, 0, PixelFormat32bppARGB, 0, @hBitmap_Bg)
437 GdipGetImageGraphicsContext(hBitmap_Bg, @hGfx_Bg)
438 GdipSetSmoothingMode(hGfx_Bg, 6)
439 GdipSetPixelOffsetMode(hGfx_Bg, PixelOffsetModeHalf)
440
441 Dim As GpPointF tPoint
442 tPoint.x = fCx
443 tPoint.y = fCy
444 Dim As Ulong iCnt = 1, iColor = &hFFB0B0B0
445 GdipCreatePath(0, @hPath)
446 GdipAddPathEllipse(hPath, 4, 4, iW - 9, iH - 9)
447 GdipCreatePathGradientFromPath(hPath, @hBrush2)
448 GdipSetPathGradientCenterColor(hBrush2, &hF0FFFFFF)
449 GdipSetPathGradientCenterPoint(hBrush2, @tPoint)
450 GdipSetPathGradientSurroundColorsWithCount(hBrush2, @iColor, @iCnt)
451 GdipSetPathGradientGammaCorrection(hBrush2, True)
452
453 GdipFillEllipse(hGfx_Bg, hBrush2, 4, 4, iW - 9, iH - 9)
454 GdipDrawEllipse(hGfx_Bg, hPen2, 4, 4, iW - 9, iH - 9)
455
456
457 GdipCreateSolidFill(&hFF200000, @hBrush_c)
458
459 GdipCreateStringFormat(0, 0, @hFormat)
460 GdipCreateFontFamilyFromName("Consolas", 0, @hFamily)
461
462 GdipCreateBitmapFromScan0(iW, iH, 0, PixelFormat32bppARGB, 0, @hBitmap)
463 GdipGetImageGraphicsContext(hBitmap, @hGfx)
464 GdipSetSmoothingMode(hGfx, 6)
465 GdipSetPixelOffsetMode(hGfx, PixelOffsetModeHalf)
466 GdipSetInterpolationMode(hGfx, InterpolationModeHighQualityBicubic)
467 GdipSetCompositingQuality(hGfx, CompositingQualityGammaCorrected)
468
469 GdipCreateBitmapFromScan0(fSize2, fSize2, 0, PixelFormat32bppARGB, 0, @hBitmap_Cursor)
470 GdipGetImageGraphicsContext(hBitmap_Cursor, @hGfx_Cursor)
471 GdipSetSmoothingMode(hGfx_Cursor, 6)
472 GdipSetPixelOffsetMode(hGfx_Cursor, PixelOffsetModeHalf)
473 GdipSetInterpolationMode(hGfx_Cursor, InterpolationModeHighQualityBicubic)
474 GdipSetCompositingQuality(hGfx_Cursor, CompositingQualityGammaCorrected)
475
476 GdipCreateMatrix(@hMatrix)
477 GdipCreateMatrix(@hMatrix2)
478
479 GdipSetStringFormatAlign(hFormat, StringAlignmentCenter)
480 GdipSetStringFormatLineAlign(hFormat, StringAlignmentCenter)
481
482 For i = 0 To iLen - 1
483 GdipCreateBitmapFromScan0(fSize, fSize, 0, PixelFormat32bppARGB, 0, @tCoord(i).img)
484 GdipGetImageGraphicsContext(tCoord(i).img, @tCoord(i).gfx)
485 GdipSetSmoothingMode(tCoord(i).gfx, 6)
486 GdipSetPixelOffsetMode(tCoord(i).gfx, PixelOffsetModeHalf)
487 GdipSetTextRenderingHint(tCoord(i).gfx, TextRenderingHintAntiAliasGridFit)
488 Next
489
490
491 Dim As Bool bSkipSleep = False
492 For i = iLen - 1 To 0 Step - 1
493 GdipDrawImageRect(hCanvas, hBitmap_Bg, 0, 0, iW, iH)
494 GdipDrawImageRect(hCanvas, hBitmap, 0, 0, iW, iH)
495
496 fDegree = fDAngle + iLen / c4 * i
497 tCoord(i).x = fCx + Sin(fDegree * fRad) * fRadius / c6
498 tCoord(i).y = fCy + Cos(fDegree * fRad) * fRadius / c7
499 fRadius -= c5 / iLen
500 fFontSize = fRadius / 7
501
502 mwx = tCoord(i).x - fCx
503 mwy = fCy - tCoord(i).y
504 c3 = (mwx + Sqr(mwx * mwx + mwy * mwy))
505 fAngle = 2 * -ATn(mwy / c3) * fDeg
506 If c3 = 0 Then
507 If mwx < 0 Then
508 fAngle = -180
509 Else
510 fAngle = 180
511 End If
512 End If
513 f1 = iDX + c1
514 f2 = iDY + c1
515
516 If i < (iLen - 1) Then
517 GdipSetPenWidth(hPen, fFontSize / 8)
518 GdipDrawLine(hCanvas, hPen, tCoord(i).x + f1, tCoord(i).y + f2, tCoord(i + 1).x + f1, tCoord(i + 1).y + f2)
519 GdipDrawLine(hGfx, hPen, tCoord(i).x + f1, tCoord(i).y + f2, tCoord(i + 1).x + f1, tCoord(i + 1).y + f2)
520 Endif
521
522 GdipSetMatrixElements(hMatrix, 1, 0, 0, 1, 0, 0)
523 GdipTranslateMatrix(hMatrix, c1, c1, False)
524 GdipRotateMatrix(hMatrix, 90 + fAngle, False)
525 GdipTranslateMatrix(hMatrix, -c1, -c1, False)
526 GdipSetWorldTransform(tCoord(i).gfx, hMatrix)
527
528 GdipSetMatrixElements(hMatrix2, 1, 0, 0, 1, 0, 0)
529 GdipTranslateMatrix(hMatrix2, c2, c2, False)
530 GdipRotateMatrix(hMatrix2, 90 + fAngle, False)
531 GdipTranslateMatrix(hMatrix2, -c2, -c2, False)
532 GdipSetWorldTransform(hGfx_Cursor, hMatrix2)
533
534
535 GdipGraphicsClear(hGfx_Cursor, 0)
536 GdipFillRectangle(hGfx_Cursor, hBrush_c, fSize * 0.475, fSize * 0.1, fSize * 1.05, fSize * 1.55)
537
538 fFontSize = Iif(fFontSize < 0.5, 0.5, fFontSize)
539 GdipCreateFont(hFamily, fFontSize, 0, 3, @hFont)
540
541 tLayout.x = 0
542 tLayout.y = 0
543 tLayout.width = fSize
544 tLayout.height = fSize
545
546 GdipDrawString(tCoord(i).gfx, aText(i), -1, hFont, @tLayout, hFormat, hBrush)
547 GdipDrawImageRect(hCanvas, tCoord(i).img, iDX + tCoord(i).x, iDY + tCoord(i).y, fSize, fSize)
548 GdipDrawImageRect(hGfx, tCoord(i).img, iDX + tCoord(i).x, iDY + tCoord(i).y, fSize, fSize)
549 GdipDrawImageRect(hCanvas, hBitmap_Cursor, tCoord(i).x + f1 - fFontSize, tCoord(i).y + f2 - fFontSize, fFontSize * 2, fFontSize * 2)
550
551
552 'GdipDrawLine(hCanvas, hPen2, 0, fCy, iW, fCy)
553 'GdipDrawLine(hCanvas, hPen2, fCx, 0, fCx, iH)
554
555 BitBlt(hDC, 0, 0, iW, iH, hDC_backbuffer, 0, 0, SRCCOPY)
556
557 GdipDeleteFont(hFont)
558 GdipGraphicsClear(hCanvas, &hFF606E8C)
559
560 If bSkipSleep = False Then Sleep(175)
561 If InKey = Chr(32) Then bSkipSleep = True
562 Next
563
564 GdipSetMatrixElements(hMatrix, 1, 0, 0, 1, 0, 0)
565 Dim e As Event
566 Do
567
568 GdipTranslateMatrix(hMatrix, fCx, fCy, False)
569 GdipRotateMatrix(hMatrix, -0.2, False)
570 GdipTranslateMatrix(hMatrix, -fCx, -fCy, False)
571 GdipSetWorldTransform(hCanvas, hMatrix)
572 GdipDrawImageRect(hCanvas, hBitmap_Bg, 0, 0, iW, iH)
573 GdipDrawImageRect(hCanvas, hBitmap, 0, 0, iW, iH)
574 BitBlt(hDC, 0, 0, iW, iH, hDC_backbuffer, 0, 0, SRCCOPY)
575 GdipGraphicsClear(hCanvas, &hFF606E8C)
576
577 Sleep(1, 1)
578 If (ScreenEvent(@e)) Then
579 Select Case e.type
580 Case EVENT_WINDOW_CLOSE
581 Exit Do
582 End Select
583 End If
584 Loop Until InKey = Chr(27)
585
586 GdipDeletePath(hPath)
587 GdipDeleteFontFamily(hFamily)
588 GdipDeleteStringFormat(hFormat)
589 GdipDeletePen(hPen)
590 GdipDeletePen(hPen2)
591 GdipDeleteBrush(hBrush)
592 GdipDeleteBrush(hBrush2)
593 GdipDeleteBrush(hBrush_c)
594 GdipDeleteMatrix(hMatrix)
595 GdipDeleteMatrix(hMatrix2)
596 For i = 0 To iLen - 1
597 GdipDeleteGraphics(tCoord(i).gfx)
598 GdipDisposeImage(tCoord(i).img)
599 Next
600 GdipDeleteGraphics(hGfx)
601 GdipDisposeImage(hBitmap)
602 GdipDeleteGraphics(hGfx_Cursor)
603 GdipDisposeImage(hBitmap_Cursor)
604 GdipDeleteGraphics(hGfx_Bg)
605 GdipDisposeImage(hBitmap_Bg)
606 SelectObject(hDC_backbuffer, hObjOld)
607 DeleteDC(hDC_backbuffer)
608 ReleaseDC(hHWND, hDC)
609
610 TitchySID.Stop()
611 TitchySID.Close()
612
613 Screenres iW, iH, 32, , GFX_NULL 'send GUI to nirvana
614 'DestroyWindow(hHWND) 'doesn't work
615 'SendMessage(hHWND, WM_CLOSE, 0, 0) 'doesn't work
616End Sub
617
618Sub BaseEncoder(aFiles As tFileArray, iLineLen As Ushort = 992)
619 Dim As Ulong iFileSize, iCompressedSize, iSizeBase
620 Dim As Integer hFile
621 Dim As Ulong i, j, iCompressionFormatAndEngine = 5, iChars, iLines, iCompression_tmp
622 Dim As Ubyte Ptr pMem, pMemCompressed
623 Dim As String sBaseEncoded, sCodeFile, sBaseCode = "'Code below was generated by: " & sTitle & CRLF & CRLF, sLine, sHeader
624
625 SendMessage(hProgressbar, PBM_SETRANGE, 0, MAKELPARAM(0, Ubound(aFiles.files) + 1))
626 SendMessage(hProgressbar, PBM_SETPOS, 0, 0)
627 For i = 0 To Ubound(aFiles.files)
628 SendMessage(hProgressbar, PBM_STEPIT, 0, 0)
629 iFileSize = Filelen(aFiles.files(i))
630 pMem = Allocate(iFileSize)
631 hFile = Freefile()
632 Open aFiles.files(i) For Binary Access Read As #hFile
633 Get #hFile, 0, pMem[0], iFileSize
634 Close #hFile
635
636 iSizeBase = 0
637 iCompression_tmp = iCompression
638
639 If iCompression Then
640 If bProbeAllCompressors Then
641 Dim As Ubyte iBest = 0, j
642 Dim As Ulong iProbeSize = &hFFFFFFFF
643 Dim As Ubyte Ptr aMemCompressed(2 To 6)
644 For j = 2 To 6
645 Select Case j
646 Case 2 To 4
647 aMemCompressed(j) = _WinAPI_RtlCompress(pMem, iFileSize, iCompressedSize, bMaxCompression, j)
648 Case 5
649 Dim As Ulong iMem = iFileSize Shl 2
650 aMemCompressed(j) = Allocate(iMem)
651 iCompressedSize = iMem
652 lzfx_compress(pMem, iFileSize, aMemCompressed(j), iCompressedSize)
653 Case 6
654 iCompressedSize = compressBound(iFileSize)
655 aMemCompressed(j) = Allocate(iCompressedSize)
656 compress(aMemCompressed(j), @iCompressedSize, pMem, iFileSize)
657 End Select
658
659 ? j & ": " & iCompressedSize
660 If iCompressedSize < iProbeSize And iCompressedSize < iFileSize Then
661 iProbeSize = iCompressedSize
662 iBest = j
663 End If
664 Next
665
666 ? "Best compression: " & iBest
667 ? "------------------------------"
668 For j = 2 To 6
669 If j <> iBest Then Deallocate(aMemCompressed(j))
670 Next
671 iCompressedSize = Iif(iProbeSize = &hFFFFFFFF, 0, iProbeSize)
672 pMemCompressed = aMemCompressed(iBest)
673 iCompression = iBest - 1
674 iCompression_tmp = iCompression
675 Select Case iCompression
676 Case 1
677 iCompressionFormatAndEngine = COMPRESSION_FORMAT_LZNT1
678 Case 2
679 iCompressionFormatAndEngine = COMPRESSION_FORMAT_XPRESS
680 Case 3
681 iCompressionFormatAndEngine = COMPRESSION_FORMAT_XPRESS_HUFF
682 Case 4
683 iCompressionFormatAndEngine = 5 'LZFX
684 Case Else
685 iCompressionFormatAndEngine = 6 'ZLib
686 End Select
687 Else
688 Select Case iCompression
689 Case 1
690 iCompressionFormatAndEngine = COMPRESSION_FORMAT_LZNT1
691 Case 2
692 iCompressionFormatAndEngine = COMPRESSION_FORMAT_XPRESS
693 Case 3
694 iCompressionFormatAndEngine = COMPRESSION_FORMAT_XPRESS_HUFF
695 End Select
696
697 If iCompression < 4 Then 'use windows built-in api for compression
698 pMemCompressed = _WinAPI_RtlCompress(pMem, iFileSize, iCompressedSize, bMaxCompression, iCompressionFormatAndEngine)
699 ' hFile = Freefile()
700 ' Open "Test.bin" For Binary Access Write As #hFile
701 ' Put #hFile, 0, pMemCompressed[0], iCompressedSize
702 ' Close #hFile
703 Else
704 If iCompression = 4 Then 'LZFX
705 Dim As Ulong iMem = iFileSize Shl 2
706 pMemCompressed = Allocate(iMem)
707 iCompressedSize = iMem
708 lzfx_compress(pMem, iFileSize, pMemCompressed, iCompressedSize)
709 Else 'ZLib
710 iCompressedSize = compressBound(iFileSize)
711 pMemCompressed = Allocate(iCompressedSize)
712 compress(pMemCompressed, @iCompressedSize, pMem, iFileSize)
713 End If
714 Endif
715 End If
716 If iCompressedSize >= iFileSize Or iCompressedSize = 0 Then
717 Select Case iBaseEncoder
718 Case 0
719 sBaseEncoded = _WinAPI_Base64Encode(pMem, iFileSize, iSizeBase)
720 Case 1
721 sBaseEncoded = Base91Encode(pMem, iFileSize, iSizeBase)
722 Case 2
723 sBaseEncoded = Base128Encode(pMem, iFileSize, iSizeBase)
724 End Select
725 iCompression_tmp = 0
726 '? "Compressed size larger than original file size. Compression skipped..."
727 Else
728 Select Case iBaseEncoder
729 Case 0
730 sBaseEncoded = _WinAPI_Base64Encode(pMemCompressed, iCompressedSize, iSizeBase)
731 Case 1
732 sBaseEncoded = Base91Encode(pMemCompressed, iCompressedSize, iSizeBase)
733 Case 2
734 sBaseEncoded = Base128Encode(pMemCompressed, iCompressedSize, iSizeBase)
735 End Select
736
737 End If
738 Deallocate(pMemCompressed)
739 Else
740 Select Case iBaseEncoder
741 Case 0
742 sBaseEncoded = _WinAPI_Base64Encode(pMem, iFileSize, iSizeBase)
743 Case 1
744 sBaseEncoded = Base91Encode(pMem, iFileSize, iSizeBase)
745 Case 2
746 sBaseEncoded = Base128Encode(pMem, iFileSize, iSizeBase)
747 End Select
748 End If
749 Deallocate(pMem)
750 ? "Base string length: " & Len(sBaseEncoded)
751
752 sCodeFile = ""
753 iLines = 0
754 iChars = 0
755 sLine = ""
756 If iSizeBase > iLineLen Then
757 For j = 1 To iSizeBase
758 sLine &= Mid(sBaseEncoded, j, 1)
759 iChars += 1
760 If iChars = iLineLen Then
761 iChars = 0
762 sCodeFile &= "Data """ & sLine & """" & CRLF
763 iLines += 1
764 sLine = ""
765 End If
766 Next
767 If sLine <> "" Then
768 sCodeFile &= "Data """ & sLine & """" & CRLF
769 iLines += 1
770 End If
771 Else
772 iLines = 1
773 sCodeFile &= "Data """ & sBaseEncoded & """" & CRLF
774 End If
775
776 sHeader = "'" & Right(aFiles.files(i), Len(aFiles.files(i)) - Instrrev(aFiles.files(i), "\")) & CRLF & _
777 "__Label" & i & ":" & CRLF & _
778 "Data " & iLines & "," & Iif(iCompression <> iCompression_tmp, 0, iCompressionFormatAndEngine) & "," & iFileSize & "," & iCompressedSize & ",""" & aBaseEncoder(iBaseEncoder) & """" & CRLF
779 sBaseCode &= sHeader & sCodeFile & Iif(Ubound(aFiles.files) > i, CRLF & CRLF, "")
780 Next
781 SendMessage(hProgressbar, PBM_SETPOS, 0, 0)
782 _WinAPI_FlashWindowEx(hGUI)
783 If bOutputClipboard Then
784 Dim As Byte hClipboard = OpenClipboard(hGUI)
785 If hClipboard = 0 Then
786 MessageBox(hGUI, "Error opening the clipboard", "ERROR", MB_OK)
787 Else
788 If EmptyClipboard() = 0 Then
789 CloseClipboard()
790 MessageBox(hGUI, "Error cleaning the clipboard", "ERROR", MB_OK)
791 Else
792 Dim As Any Ptr pMemClip, hMemClip = GlobalAlloc(GMEM_MOVEABLE Or GMEM_SHARE, Len(sBaseCode) + 1)
793 pMemClip = GlobalLock(hMemClip)
794 CopyMemory(pMemClip, Strptr(sBaseCode), Len(sBaseCode))
795 GlobalUnlock(pMemClip)
796 SetClipboardData(CF_TEXT, hMemClip)
797 CloseClipboard()
798 MessageBox(hGUI, "Generated code has been copied to clipboard.", "Information", MB_ICONINFORMATION Or MB_OK)
799 GlobalFree(hMemClip)
800 End If
801 End If
802 End If
803 If bOutputFile Then
804 Dim As Ubyte bSaveFile = 1
805 Dim As String sFile = FileSaveDialog("Save generated FB code", "", "FreeBasic (*.bas)" + Chr(0) + "*.bas" + Chr(0))
806 If sFile <> "" Then
807 If Fileexists(sFile) Then
808 If MessageBox(hGUI, "File exists - overwrite?", "Warning", MB_YESNO Or MB_ICONQUESTION) = 7 Then bSaveFile = 0
809 End If
810 If bSaveFile Then
811 hFile = Freefile()
812 If Right(sFile, 4) <> ".bas" Then sFile = sFile & ".bas"
813 Open sFile For Binary Access Write As #hFile
814 Put #hFile, 0, sBaseCode
815 Close #hFile
816 MessageBox(hGUI, "Generated code has been saved to disk.", "Information", MB_ICONINFORMATION Or MB_OK)
817 End If
818 End If
819 End If
820 _WinAPI_FlashWindowEx(hGUI, FLASHW_STOP)
821End Sub
822
823Function WndProc(hWnd As HWND, uMsg As UINT, wParam As WPARAM, lParam As LPARAM) As Integer
824 Select Case uMsg
825 Case WM_SETCURSOR
826 SetCursor(Cast(HCURSOR, hAnim))
827 Return 0
828 Case WM_NOTIFY
829
830 Case WM_SHELLNOTIFY
831 If lParam = WM_RBUTTONDOWN Then
832 Dim tPOINT As Point
833 GetCursorPos(@tPOINT)
834 SetForegroundWindow(hWnd)
835 TrackPopupMenuEx(TrayMenu, TPM_LEFTALIGN Or TPM_RIGHTBUTTON, tPOINT.x, tPOINT.y, hWnd, NULL)
836 PostMessage(hWnd, WM_NULL, 0, 0)
837 End If
838
839 Case WM_DROPFILES
840 Dim As Ulong iCnt = DragQueryFileW(Cast(HDROP, wParam), -1, 0, 0)
841 If iCnt > 0 Then
842 bFilesAdded = 0
843 iFilesAdded = 0
844 Dim As Ulong iSumFileSizes = 0
845 Dim As Wstring * 4096 tFiles
846 Redim aFiles.files(0 To iCnt - 1)
847 For i As Ulong = 0 To iCnt - 1
848 DragQueryFileW(Cast(HDROP, wParam), i, Cast(LPWSTR, @tFiles), Sizeof(tFiles))
849 If PathIsDirectoryW(tFiles) = 0 Then 'files only
850 iSumFileSizes + = Filelen(tFiles)
851 If iSumFileSizes > iMaxFilesizeSum Then
852 MessageBox(hGUI, "Sum of file sizes has exceeded 100 MB - skipping the rest of the " & Ubound(aFiles.files) - i & " files!", "Information", MB_ICONWARNING Or MB_OK)
853 Exit For
854 End If
855 aFiles.files(iFilesAdded) = tFiles
856 bFilesAdded = 1
857 iFilesAdded += 1
858 End If
859 Next
860 If bFilesAdded Then
861 iFilesAdded -= 1
862 Redim Preserve aFiles.files(0 To iFilesAdded)
863 BaseEncoder(aFiles)
864 Return 0
865 Else
866 MessageBox(hGUI, "No files were added!" & CRLF & "Directories are not supported!", "Information", MB_ICONWARNING Or MB_OK)
867 End If
868 End If
869 Return 0
870 Case WM_COMMAND
871 Select Case Loword (wParam)
872 Case id_TrayReset
873 SetWindowPos(hGUI, HWND_TOP, iDefaultPosX, iDefaultPosY, 0, 0, SWP_NOSIZE)
874 Return 0
875 Case id_Exit, id_TrayExit
876 GetWindowRect(hGUI, @tPos)
877 DestroyWindow(hGUI)
878 Return 0
879 Case id_EncoderB64, id_EncoderB91, id_EncoderB128
880 Select Case Loword (wParam)
881 Case id_EncoderB64
882 iBaseEncoder = 0
883 CheckMenuRadioItem(hMenuSub1, 0, 2, 0, MF_BYPOSITION)
884 Case id_EncoderB91
885 iBaseEncoder = 1
886 CheckMenuRadioItem(hMenuSub1, 0, 2, 1, MF_BYPOSITION)
887 Case id_EncoderB128
888 iBaseEncoder = 2
889 CheckMenuRadioItem(hMenuSub1, 0, 2, 2, MF_BYPOSITION)
890 End Select
891 Return 0
892 Case id_CompressionDisabled, id_CompressionLZNT1, id_CompressionXPRESS, id_CompressionXPRESSHUFF, id_CompressionLZFX, id_CompressionZlib
893 Select Case Loword (wParam)
894 Case id_CompressionDisabled
895 iCompression = 0
896 CheckMenuRadioItem(hMenuSub2, 0, iMaxMenuSub2Items, 0, MF_BYPOSITION)
897 EnableMenuItem(hMenuSub2, id_ProbeAllCompressors, MF_DISABLED or MF_GRAYED)
898 Case id_CompressionLZNT1
899 iCompression = 1
900 CheckMenuRadioItem(hMenuSub2, 0, iMaxMenuSub2Items, 1, MF_BYPOSITION)
901 EnableMenuItem(hMenuSub2, id_ProbeAllCompressors, MF_ENABLED)
902 Case id_CompressionXPRESS
903 iCompression = 2
904 CheckMenuRadioItem(hMenuSub2, 0, iMaxMenuSub2Items, 2, MF_BYPOSITION)
905 EnableMenuItem(hMenuSub2, id_ProbeAllCompressors, MF_ENABLED)
906 Case id_CompressionXPRESSHUFF
907 iCompression = 3
908 CheckMenuRadioItem(hMenuSub2, 0, iMaxMenuSub2Items, 3, MF_BYPOSITION)
909 EnableMenuItem(hMenuSub2, id_ProbeAllCompressors, MF_ENABLED)
910 Case id_CompressionLZFX
911 iCompression = 4
912 CheckMenuRadioItem(hMenuSub2, 0, iMaxMenuSub2Items, 4, MF_BYPOSITION)
913 EnableMenuItem(hMenuSub2, id_ProbeAllCompressors, MF_ENABLED)
914 Case id_CompressionZlib
915 iCompression = 5
916 CheckMenuRadioItem(hMenuSub2, 0, iMaxMenuSub2Items, 5, MF_BYPOSITION)
917 EnableMenuItem(hMenuSub2, id_ProbeAllCompressors, MF_ENABLED)
918 End Select
919 Return 0
920 Case id_CompressionMaxCompression
921 Dim As MENUITEMINFOA tMenu
922 tMenu.cbsize = Sizeof(tMenu)
923 tMenu.fMask = MIIM_STATE
924 GetMenuItemInfoW(hMenuSub2, iMaxMenuSub2Items + 2, TRUE, Cast(LPMENUITEMINFOW, @tMenu))
925 If tMenu.fState = MF_CHECKED Then
926 CheckMenuItem(hMenuSub2, id_CompressionMaxCompression, MF_UNCHECKED)
927 bMaxCompression = 0
928 Else
929 CheckMenuItem(hMenuSub2, id_CompressionMaxCompression, MF_CHECKED)
930 bMaxCompression = 1
931 End If
932 Return 0
933 Case id_ProbeAllCompressors
934 Dim As MENUITEMINFOA tMenu
935 tMenu.cbsize = Sizeof(tMenu)
936 tMenu.fMask = MIIM_STATE
937 GetMenuItemInfoW(hMenuSub2, iMaxMenuSub2Items + 4, TRUE, Cast(LPMENUITEMINFOW, @tMenu))
938 If tMenu.fState = MF_CHECKED Then
939 CheckMenuItem(hMenuSub2, id_ProbeAllCompressors, MF_UNCHECKED)
940 bProbeAllCompressors = 0
941 EnableMenuItem(hMenuSub2, id_CompressionDisabled, MF_ENABLED)
942 EnableMenuItem(hMenuSub2, id_CompressionLZNT1, MF_ENABLED)
943 EnableMenuItem(hMenuSub2, id_CompressionXPRESS, MF_ENABLED)
944 EnableMenuItem(hMenuSub2, id_CompressionXPRESSHUFF, MF_ENABLED)
945 EnableMenuItem(hMenuSub2, id_CompressionLZFX, MF_ENABLED)
946 EnableMenuItem(hMenuSub2, id_CompressionZLib, MF_ENABLED)
947 Else
948 CheckMenuItem(hMenuSub2, id_ProbeAllCompressors, MF_CHECKED)
949 bProbeAllCompressors = 1
950 EnableMenuItem(hMenuSub2, id_CompressionDisabled, MF_DISABLED or MF_GRAYED)
951 EnableMenuItem(hMenuSub2, id_CompressionLZNT1, MF_DISABLED or MF_GRAYED)
952 EnableMenuItem(hMenuSub2, id_CompressionXPRESS, MF_DISABLED or MF_GRAYED)
953 EnableMenuItem(hMenuSub2, id_CompressionXPRESSHUFF, MF_DISABLED or MF_GRAYED)
954 EnableMenuItem(hMenuSub2, id_CompressionLZFX, MF_DISABLED or MF_GRAYED)
955 EnableMenuItem(hMenuSub2, id_CompressionZLib, MF_DISABLED or MF_GRAYED)
956 End If
957 Return 0
958 Case id_OutputFile
959 Dim As MENUITEMINFOA tMenu
960 tMenu.cbsize = Sizeof(tMenu)
961 tMenu.fMask = MIIM_STATE
962 GetMenuItemInfoW(hMenuSub3, 0, TRUE, Cast(LPMENUITEMINFOW, @tMenu))
963 If tMenu.fState = MF_CHECKED And bOutputClipboard = 1 Then
964 CheckMenuItem(hMenuSub3, id_OutputFile, MF_UNCHECKED)
965 bOutputFile = 0
966 Else
967 CheckMenuItem(hMenuSub3, id_OutputFile, MF_CHECKED)
968 bOutputFile = 1
969 End If
970 Return 0
971 Case id_OutputClipboard
972 Dim As MENUITEMINFOA tMenu
973 tMenu.cbsize = Sizeof(tMenu)
974 tMenu.fMask = MIIM_STATE
975 GetMenuItemInfoW(hMenuSub3, 1, TRUE, Cast(LPMENUITEMINFOW, @tMenu))
976 If tMenu.fState = MF_CHECKED And bOutputFile = 1 Then
977 CheckMenuItem(hMenuSub3, id_OutputClipboard, MF_UNCHECKED)
978 bOutputClipboard = 0
979 Else
980 CheckMenuItem(hMenuSub3, id_OutputClipboard, MF_CHECKED)
981 bOutputClipboard = 1
982 End If
983 Return 0
984 Case id_About, id_TrayAbout
985 'MessageBox(hGUI, sTitle & CRLF & CRLF & "Coded by UEZ", "About", MB_OK)
986 About()
987 Return 0
988 End Select
989 Case WM_CONTEXTMENU
990 Dim tPOINT As Point
991 GetCursorPos(@tPOINT)
992 SetForegroundWindow(hWnd)
993 TrackPopupMenuEx(hMenuMain, TPM_LEFTALIGN Or TPM_RIGHTBUTTON, tPOINT.x, tPOINT.y, hWnd, NULL)
994 PostMessage(hWnd, WM_NULL, 0, 0)
995 Return 0
996 Case WM_KEYDOWN
997 If wParam = VK_ESCAPE Then
998 GetWindowRect(hGUI, @tPos)
999 DestroyWindow(hGUI)
1000 Endif
1001 Return 0
1002 Case WM_CLOSE, WM_DESTROY
1003 PostQuitMessage(0)
1004 Return 0
1005 Case WM_LBUTTONDOWN 'move GUI
1006 SendMessageW(hGUI, WM_SYSCOMMAND, SC_DRAGMOVE, 0)
1007 Return 0
1008 Case WM_DRAWITEM
1009
1010 End Select
1011 Return DefWindowProc(hWnd, uMsg, wParam, lParam)
1012End Function
1013
1014Sub _WinAPI_InsertMenuItem(hMenuMain As HMENU, iItem As Uinteger, sText As String, iID As Uinteger = 0, hSubMenu As HMENU = 0, hBitmap As Any Ptr = 0, iBGColor As Integer = COLOR_HIGHLIGHTTEXT)
1015 Dim As MENUITEMINFOA tMenuItem
1016 With tMenuItem
1017 .cbsize = Sizeof(tMenuItem)
1018 .wID = iID
1019 .hSubMenu = hSubMenu
1020 If sText = "" Then
1021 .fMask = MIIM_FTYPE
1022 .fType = MFT_SEPARATOR
1023 Else
1024 .fMask = MIIM_ID Or MIIM_STRING Or MIIM_SUBMENU Or MIIM_BITMAP 'Or MIIM_STATE Or MIIM_TYPE
1025 .fType = MFT_OWNERDRAW Or MFT_STRING
1026 If hBitmap <> 0 Then .hbmpItem = hBitmap
1027 End If
1028 End With
1029
1030 Dim As Wstring * 260 tMenuText = sText
1031 tMenuItem.dwTypeData = Cast(LPTSTR, @tMenuText)
1032 InsertMenuItemW(hMenuMain, iItem, True, Cast(LPCMENUITEMINFOW, @tMenuItem))
1033
1034 Dim As MENUINFO tMenuBgColor
1035 With tMenuBgColor
1036 .cbSize = Sizeof(MENUINFO)
1037 .fMask = MIM_BACKGROUND
1038 .hbrBack = GetSysColorBrush(iBGColor)
1039 End With
1040 SetMenuInfo(hMenuMain, Cast(LPCMENUINFO, @tMenuBgColor))
1041End Sub
1042
1043'https://msdn.microsoft.com/en-us/library/windows/desktop/hh298368(v=vs.85).aspx
1044Function _WinAPI_CreateToolTip(hDlg As HWND, sToolTipText As String, bBalloon As Ubyte = 1, iWidth As Ushort = 500, toolID As Integer = 0) As HWND
1045 If hDlg = 0 Or Len(sToolTipText) = 0 Then Return 0
1046 If Len(sToolTipText) > 79 Then Left(sToolTipText, 79)
1047 Dim hToolTip As HWND
1048
1049 bBalloon = Iif(bBalloon > 1, 1, bBalloon)
1050 Dim As Long iStyle = bBalloon * TTS_BALLOON
1051 hToolTip = CreateWindowEx(Null, TOOLTIPS_CLASS, NULL, _
1052 TTS_NOPREFIX Or TTS_ALWAYSTIP Or TTS_BALLOON Or iStyle, _
1053 CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, _
1054 hDlg, Null, Null, Null)
1055
1056 If hToolTip = 0 Then Return 0
1057 SetWindowPos(hToolTip, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE Or SWP_NOSIZE Or SWP_NOACTIVATE)
1058 SendMessage(hToolTip, TTM_SETTIPBKCOLOR, &hFFFFFF, 0)
1059 SendMessage(hToolTip, TTM_SETTIPTEXTCOLOR, &h000000, 0)
1060 SendMessage(hToolTip, TTM_SETMAXTIPWIDTH, 0, iWidth) 'multi line tooltip text
1061
1062 Dim As HWND hwndTool = GetDlgItem(hDlg, toolID)
1063 Dim tToolInfo As TOOLINFO
1064 With tToolInfo
1065 .cbSize = Sizeof(tToolInfo)
1066 .uFlags = TTF_SUBCLASS
1067 .hwnd = hDlg
1068 .hinst = Null
1069 .lpszText = Strptr(sToolTipText)
1070 .uId = Cptr(UINT_PTR, hwndTool)
1071 End With
1072 GetClientRect(hDlg, @tToolInfo.rect)
1073
1074 SendMessage(hToolTip, TTM_ADDTOOL, 0, Cast(LPARAM, @tToolInfo))
1075
1076 Return hToolTip
1077End Function
1078
1079'https://msdn.microsoft.com/en-us/library/ms724353.aspx
1080Function _WinAPI_IniRead(sIniFile As String, sSection As String, sKey As String, sDefault As String = "default") As String
1081 Dim As Zstring * 1024 Buffer
1082 Dim As Integer iResult = GetPrivateProfileString(sSection, sKey, sDefault, @Buffer, Sizeof(Buffer), sIniFile)
1083 Return Buffer
1084End Function
1085
1086'https://msdn.microsoft.com/en-us/library/ms725500(v=vs.85).aspx
1087Function _WinAPI_IniWrite(sIniFile As String, sSection As String, sKey As String, sValue As String = "default") As Integer
1088 Dim As Zstring * 1024 Buffer
1089 Dim As Integer iResult = WritePrivateProfileString(sSection, sKey, sValue, sIniFile)
1090 Return iResult
1091End Function
1092
1093'https://docs.microsoft.com/en-us/windows/desktop/api/winuser/nf-winuser-flashwindowex
1094Function _WinAPI_FlashWindowEx(hWND As HWND, iFlag As DWORD = FLASHW_ALL, iCount As ULong = 10, iTimeOut As DWORD = 500) As Integer
1095 Dim As FLASHWINFO tFLASH
1096 tFlash.cbSize = Sizeof(FLASHWINFO)
1097 tFlash.hwnd = hGUI
1098 tFlash.dwFlags = iFlag
1099 tFlash.uCount = iCount
1100 tFlash.dwTimeout = iTimeOut
1101 Return FlashWindowEx(Cast(PFLASHWINFO, @tFLASH))
1102End Function
1103
1104'https://docs.microsoft.com/en-us/windows-hardware/drivers/ddi/content/ntifs/nf-ntifs-rtlcompressbuffer
1105Function _WinAPI_RtlCompress(pBinary As Ubyte Ptr, iBinarySize As Ulong, Byref iCompressedSize As Ulong, bMaxCompression As Ubyte = 1, iCompressionEngine As Ushort = COMPRESSION_FORMAT_LZNT1) As Ubyte Ptr
1106 Dim As Any Ptr hLib = Dylibload("Ntdll.dll")
1107
1108 Dim pRtlGetCompressionWorkSpaceSize As Function _
1109 (Byval CompressionFormatAndEngine As Ushort, _
1110 Byval CompressBufferWorkSpaceSize As Ulong Ptr, _
1111 Byval CompressFragmentWorkSpaceSize As Ulong Ptr) As Ulong
1112
1113
1114 Dim pRtlCompressBuffer As Function _
1115 (Byval CompressionFormatAndEngine As Ushort, _
1116 Byval UncompressedBuffer As Ubyte Ptr, _
1117 Byval UncompressedBufferSize As Ulong, _
1118 Byval CompressedBuffer As Ubyte Ptr, _
1119 Byval CompressedBufferSize As Ulong, _
1120 Byval UncompressedBufferSize As Ulong, _
1121 Byval FinalCompressedSize As Ulong Ptr, _
1122 Byval WorkSpace As Ubyte Ptr) As Ulong
1123
1124 pRtlGetCompressionWorkSpaceSize = Dylibsymbol(hLib, "RtlGetCompressionWorkSpaceSize")
1125 pRtlCompressBuffer = Dylibsymbol(hLib, "RtlCompressBuffer")
1126
1127 Dim As Ulong iReturn, iCompressBufferWorkSpaceSize, iCompressFragmentWorkSpaceSize, iFinalCompressedSize = 0
1128 Dim As Ushort iCompressionFormatAndEngine = Iif(bMaxCompression, iCompressionEngine Or COMPRESSION_ENGINE_MAXIMUM, iCompressionEngine)
1129 iReturn = pRtlGetCompressionWorkSpaceSize(iCompressionFormatAndEngine, @iCompressBufferWorkSpaceSize, @iCompressFragmentWorkSpaceSize)
1130 Dim As Ubyte Ptr pWorkSpace = Allocate(iCompressBufferWorkSpaceSize), pBuffer = Allocate(2 * iBinarySize)
1131 iReturn = pRtlCompressBuffer(iCompressionFormatAndEngine, pBinary, iBinarySize, pBuffer, 2 * iBinarySize, 4096, @iFinalCompressedSize, pWorkSpace)
1132 iCompressedSize = iFinalCompressedSize
1133
1134 Dim As Ubyte Ptr pCompressedBuffer
1135 If iFinalCompressedSize > 0 Then
1136 pCompressedBuffer = Allocate(iFinalCompressedSize)
1137 For i As Ulong = 0 To iFinalCompressedSize - 1
1138 pCompressedBuffer[i] = pBuffer[i]
1139 Next
1140 End If
1141 Deallocate(pWorkSpace)
1142 Deallocate(pBuffer)
1143 Dylibfree(hLib)
1144 Return pCompressedBuffer
1145End Function
1146
1147'https://docs.microsoft.com/en-us/windows-hardware/drivers/ddi/content/ntifs/nf-ntifs-rtldecompressbufferex
1148Function _WinAPI_RtlDecompress(aBinary As Ubyte Ptr, iFileSize As Ulong, iCompressedSize As Ulong, iDecompressionEngine As Ushort = COMPRESSION_FORMAT_LZNT1) As Ubyte Ptr
1149
1150 Dim As Any Ptr hLib = Dylibload("Ntdll.dll")
1151
1152 Dim pRtlGetCompressionWorkSpaceSize As Function _
1153 ( Byval CompressionFormatAndEngine As Ushort, _
1154 Byval CompressBufferWorkSpaceSize As Ulong Ptr, _
1155 Byval CompressFragmentWorkSpaceSize As Ulong Ptr) As Ulong
1156
1157 Dim pRtlDecompressBufferEx As Function _
1158 ( Byval CompressionFormat As Ushort, _
1159 Byval UncompressedBuffer As Ubyte Ptr, _
1160 Byval UncompressedBufferSize As Ulong, _
1161 Byval CompressedBuffer As Ubyte Ptr, _
1162 Byval CompressedBufferSize As Ulong, _
1163 Byval FinalUncompressedSize As Ulong Ptr, _
1164 Byval WorkSpace As Ubyte Ptr) As Ulong
1165
1166 pRtlGetCompressionWorkSpaceSize = Dylibsymbol(hLib, "RtlGetCompressionWorkSpaceSize")
1167 pRtlDecompressBufferEx = Dylibsymbol(hLib, "RtlDecompressBufferEx")
1168
1169
1170 Dim As Ulong iUSize, iDecompressBufferWorkSpaceSize, iDecompressFragmentWorkSpaceSize, iReturn
1171 iReturn = pRtlGetCompressionWorkSpaceSize(iDecompressionEngine, @iDecompressBufferWorkSpaceSize, @iDecompressFragmentWorkSpaceSize)
1172 Dim As Ubyte Ptr pWorkSpace = Allocate(iDecompressBufferWorkSpaceSize), pDecompress = Allocate(iFileSize)
1173 iReturn = pRtlDecompressBufferEx(iDecompressionEngine, pDecompress, iFileSize, aBinary, iCompressedSize, @iUSize, pWorkSpace)
1174
1175 If iReturn Then
1176 ? "An Error has occured:"
1177 Select Case iReturn
1178 Case &hC0000242
1179 ? Hex(iReturn) & ": STATUS_BAD_COMPRESSION_BUFFER"
1180 Case &hC00000E8
1181 ? Hex(iReturn) & ": STATUS_INVALID_USER_BUFFER"
1182 Case &hC000025F
1183 ? Hex(iReturn) & ": STATUS_UNSUPPORTED_COMPRESSION"
1184 Case &hC000000D
1185 ? Hex(iReturn) & ": STATUS_INVALID_PARAMETER"
1186 Case &h00000117
1187 ? Hex(iReturn) & ": STATUS_BUFFER_ALL_ZEROS"
1188 Case &hC00000BB
1189 ? Hex(iReturn) & ": STATUS_NOT_SUPPORTED"
1190 Case &hC0000023
1191 ? Hex(iReturn) & ": STATUS_BUFFER_TOO_SMALL"
1192 End Select
1193 End If
1194 Deallocate(pWorkSpace)
1195 Dylibfree(hLib)
1196 Return pDecompress
1197End Function
1198
1199'Original code by KristopherWindsor -> https://www.freebasic.net/forum/viewtopic.php?f=7&t=10981&hilit=FileOpenDialog
1200Function FileSaveDialog (Byref sTitle As String, Byref sDir As String = CurDir, sFilter As String = !"All Files (*.*)" + Chr(0) + "*.*" + Chr(0, 0)) As String
1201 Dim oFilename As OPENFILENAME
1202 Dim sFilename As Zstring * (MAX_PATH + 1)
1203 Dim Title As Zstring * 32 => sTitle
1204 Dim sInitialDir As Zstring * 256 => sDir
1205
1206 With oFilename
1207 .lStructSize = SizeOf(OPENFILENAME)
1208 .hwndOwner = NULL
1209 .hInstance = GetModuleHandle(NULL)
1210 .lpstrFilter = Strptr(sFilter)
1211 .lpstrCustomFilter = NULL
1212 .nMaxCustFilter = 0
1213 .nFilterIndex = 1
1214 .lpstrFile = @sFilename
1215 .nMaxFile = SizeOf(sFilename)
1216 .lpstrFileTitle = NULL
1217 .nMaxFileTitle = 0
1218 .lpstrInitialDir = @sInitialDir
1219 .lpstrTitle = @Title
1220 .Flags = OFN_EXPLORER Or OFN_FILEMUSTEXIST Or OFN_PATHMUSTEXIST
1221 .nFileOffset = 0
1222 .nFileExtension = 0
1223 .lpstrDefExt = NULL
1224 .lCustData = 0
1225 .lpfnHook = NULL
1226 .lpTemplateName = NULL
1227 End With
1228
1229 If GetSaveFileName(@oFilename) = False Then Return ""
1230 Return sFilename
1231End Function
1232
1233Function DecompressBGImage() As Any Ptr
1234 'decompress base91 encoded image
1235 Dim As Ulong iLines, bCompressed, iFileSize, iCompressedSize
1236 Dim As String sBaseType, sBase91, aB91(1)
1237
1238 Restore __fblogopng:
1239 Read iLines
1240 Read bCompressed
1241 Read iFileSize
1242 Read iCompressedSize
1243 Read sBaseType
1244 For i As Ushort = 0 To iLines - 1
1245 Read aB91(0)
1246 sBase91 &= aB91(0)
1247 Next
1248
1249 Dim As Ulong iLenB91
1250 Static As Ubyte Ptr aBinary
1251 aBinary = Base91Decode(sBase91, iLenB91)
1252
1253 Dim As Any Ptr hBitmapGDI = _GDIPlus_BitmapCreateFromMemory3(aBinary, iLenB91, True)
1254 aBinary = 0
1255
1256 Return hBitmapGDI
1257End Function
1258
1259Function DecompressBaseImage() As any Ptr
1260 'decompress base91 encoded image
1261 Dim As Ulong iLines, bCompressed, iFileSize, iCompressedSize
1262 Dim As String sBaseType, sBase91, aB91(1)
1263
1264 Restore __bubblebazina7_24x24png:
1265 Read iLines
1266 Read bCompressed
1267 Read iFileSize
1268 Read iCompressedSize
1269 Read sBaseType
1270 For i As Ushort = 0 To iLines - 1
1271 Read aB91(0)
1272 sBase91 &= aB91(0)
1273 Next
1274
1275 Dim As Ulong iLenB91
1276 Static As Ubyte Ptr aBinary
1277 aBinary = Base91Decode(sBase91, iLenB91)
1278
1279 Dim As Any Ptr hBitmapGDI = _GDIPlus_BitmapCreateFromMemory3(aBinary, iLenB91, True)
1280 aBinary = 0
1281
1282 Return hBitmapGDI
1283End Function
1284
1285Function DecompressCompressImage() As Any Ptr
1286 'decompress base91 encoded image
1287 Dim As Ulong iLines, bCompressed, iFileSize, iCompressedSize
1288 Dim As String sBaseType, sBase91, aB91(1)
1289
1290 Restore __compresspng:
1291 Read iLines
1292 Read bCompressed
1293 Read iFileSize
1294 Read iCompressedSize
1295 Read sBaseType
1296 For i As Ushort = 0 To iLines - 1
1297 Read aB91(0)
1298 sBase91 &= aB91(0)
1299 Next
1300
1301 Dim As Ulong iLenB91
1302 Static As Ubyte Ptr aBinary
1303 aBinary = Base91Decode(sBase91, iLenB91)
1304
1305 Dim As Any Ptr hBitmapGDI = _GDIPlus_BitmapCreateFromMemory3(aBinary, iLenB91, True)
1306 aBinary = 0
1307
1308 Return hBitmapGDI
1309End Function
1310
1311Function DecompressOutputImage() As Any Ptr
1312 'decompress base91 encoded image
1313 Dim As Ulong iLines, bCompressed, iFileSize, iCompressedSize
1314 Dim As String sBaseType, sBase91, aB91(1)
1315
1316 Restore __outputpng:
1317 Read iLines
1318 Read bCompressed
1319 Read iFileSize
1320 Read iCompressedSize
1321 Read sBaseType
1322 For i As Ushort = 0 To iLines - 1
1323 Read aB91(0)
1324 sBase91 &= aB91(0)
1325 Next
1326
1327 Dim As Ulong iLenB91
1328 Static As Ubyte Ptr aBinary
1329 aBinary = Base91Decode(sBase91, iLenB91)
1330
1331 Dim As Any Ptr hBitmapGDI = _GDIPlus_BitmapCreateFromMemory3(aBinary, iLenB91, True)
1332
1333 aBinary = 0
1334
1335 Return hBitmapGDI
1336End Function
1337
1338Function DecompressAboutImage() As Any Ptr
1339 'decompress base91 encoded image
1340 Dim As Ulong iLines, bCompressed, iFileSize, iCompressedSize
1341 Dim As String sBaseType, sBase91, aB91(1)
1342
1343 Restore __aboutpng:
1344 Read iLines
1345 Read bCompressed
1346 Read iFileSize
1347 Read iCompressedSize
1348 Read sBaseType
1349 For i As Ushort = 0 To iLines - 1
1350 Read aB91(0)
1351 sBase91 &= aB91(0)
1352 Next
1353
1354 Dim As Ulong iLenB91
1355 Static As Ubyte Ptr aBinary
1356 aBinary = Base91Decode(sBase91, iLenB91)
1357
1358 Dim As Any Ptr hBitmapGDI = _GDIPlus_BitmapCreateFromMemory3(aBinary, iLenB91, True)
1359 aBinary = 0
1360
1361 Return hBitmapGDI
1362End Function
1363
1364Function DecompressExitImage() As Any Ptr
1365 'decompress base91 encoded image
1366 Dim As Ulong iLines, bCompressed, iFileSize, iCompressedSize
1367 Dim As String sBaseType, sBase91, aB91(1)
1368
1369 Restore __exitpng:
1370 Read iLines
1371 Read bCompressed
1372 Read iFileSize
1373 Read iCompressedSize
1374 Read sBaseType
1375 For i As Ushort = 0 To iLines - 1
1376 Read aB91(0)
1377 sBase91 &= aB91(0)
1378 Next
1379
1380 Dim As Ulong iLenB91
1381 Static As Ubyte Ptr aBinary
1382 aBinary = Base91Decode(sBase91, iLenB91)
1383
1384 Dim As Any Ptr hBitmapGDI = _GDIPlus_BitmapCreateFromMemory3(aBinary, iLenB91, True)
1385
1386 aBinary = 0
1387
1388 Return hBitmapGDI
1389End Function
1390
1391Function DecompressResetImage() As Any Ptr
1392 'decompress base91 encoded image
1393 Dim As Ulong iLines, bCompressed, iFileSize, iCompressedSize
1394 Dim As String sBaseType, sBase91, aB91(1)
1395
1396 Restore __resetpng:
1397 Read iLines
1398 Read bCompressed
1399 Read iFileSize
1400 Read iCompressedSize
1401 Read sBaseType
1402 For i As Ushort = 0 To iLines - 1
1403 Read aB91(0)
1404 sBase91 &= aB91(0)
1405 Next
1406
1407 Dim As Ulong iLenB91
1408 Static As Ubyte Ptr aBinary
1409 aBinary = Base91Decode(sBase91, iLenB91)
1410
1411 Dim As Any Ptr hBitmapGDI = _GDIPlus_BitmapCreateFromMemory3(aBinary, iLenB91, True)
1412
1413 aBinary = 0
1414
1415 Return hBitmapGDI
1416End Function
1417
1418Function DecompressFBIcnImage() As Any Ptr
1419 'decompress base91 encoded image
1420 Dim As Ulong iLines, bCompressed, iFileSize, iCompressedSize
1421 Dim As String sBaseType, sBase91, aB91(1)
1422
1423 Restore __fbicnpng:
1424 Read iLines
1425 Read bCompressed
1426 Read iFileSize
1427 Read iCompressedSize
1428 Read sBaseType
1429 For i As Ushort = 0 To iLines - 1
1430 Read aB91(0)
1431 sBase91 &= aB91(0)
1432 Next
1433
1434 Dim As Ulong iLenB91
1435 Static As Ubyte Ptr aBinary
1436 aBinary = Base91Decode(sBase91, iLenB91)
1437
1438 Dim As Any Ptr hBitmapGDI = _GDIPlus_BitmapCreateFromMemory3(aBinary, iLenB91, True)
1439 aBinary = 0
1440
1441 Return hBitmapGDI
1442End Function
1443
1444Function DecompressHorseAnim() As any Ptr
1445 Dim As Ulong iLines, bCompressed, iFileSize, iCompressedSize
1446 Dim As String sBaseType, sBase91, aB91(1)
1447 Restore __horseani:
1448 Read iLines
1449 Read bCompressed
1450 Read iFileSize
1451 Read iCompressedSize
1452 Read sBaseType
1453 For i As Ushort = 0 To iLines - 1
1454 Read aB91(0)
1455 sBase91 &= aB91(0)
1456 Next
1457
1458 Dim As Ulong l
1459 Dim As Ubyte Ptr aBinary = Base91Decode(sBase91, l)
1460 Dim As Boolean bError = False
1461 If bCompressed Then
1462 If iCompressedSize <> l Then bError = TRUE
1463 Else
1464 If iFileSize <> l Then bError = TRUE
1465 Endif
1466 If bError <> False Then
1467 ? "Something went wrong"
1468 Sleep
1469 End
1470 End If
1471 Dim As HICON hAnim
1472 If bCompressed Then
1473 Dim as Ubyte Ptr aBinaryC = _WinAPI_RtlDecompress(aBinary, iFileSize, iCompressedSize)
1474 hAnim = CreateIconFromResourceEx(aBinaryC, iFileSize, True, &h30000, 0, 0, LR_DEFAULTCOLOR)
1475 Deallocate(aBinaryC)
1476 Else
1477 hAnim = CreateIconFromResourceEx(aBinary, iFileSize, True, &h30000, 0, 0, LR_DEFAULTCOLOR)
1478 aBinary = 0
1479 Endif
1480 Return hAnim
1481End Function
1482
1483Sub DecompressSID()
1484 'decompress base91 encoded image
1485 Dim As Ulong iLines, bCompressed, iFileSize, iCompressedSize
1486 Dim As String sBaseType, sBase91, aB91(1)
1487
1488 Restore __sid:
1489 Read iLines
1490 Read iCompression
1491 Read iFileSize
1492 Read iCompressedSize
1493 Read sBaseType
1494 For i As Ushort = 0 To iLines - 1
1495 Read aB91(0)
1496 sBase91 &= aB91(0)
1497 Next
1498
1499 Dim As Ulong iLenB91
1500 Static As Ubyte Ptr aBinary
1501 aBinary = Base91Decode(sBase91, iLenB91)
1502
1503 Dim As Integer hFile
1504 hFile = Freefile()
1505 Open "Unicornflakes.sid" For Binary Access Write As #hFile
1506
1507 If iCompression Then
1508 Dim as Ubyte Ptr aBinaryC = _WinAPI_RtlDecompress(aBinary, iFileSize, iCompressedSize, iCompression)
1509 Put #hFile, 0, aBinaryC[0], iFileSize
1510 Deallocate(aBinaryC)
1511 Else
1512 Put #hFile, 0, aBinary[0], iFileSize
1513 Endif
1514 Close #hFile
1515 aBinary = 0
1516End Sub
1517
1518Function _GDIPlus_BitmapCreateFromMemory3(aBinImage As Ubyte Ptr, iLen As Ulong, bBitmap_GDI As Bool = False) As Any Ptr
1519 Dim As HGLOBAL hGlobal
1520 Dim As LPSTREAM hStream
1521 Dim As Any Ptr hImage_Stream
1522 Dim As Any Ptr hMemory = GlobalAlloc(GMEM_MOVEABLE, iLen)
1523 Dim As Any Ptr lpMemory = GlobalLock(hMemory)
1524 RtlCopyMemory(lpMemory, @aBinImage[0], iLen)
1525 GlobalUnlock(hMemory)
1526 CreateStreamOnHGlobal(hMemory, 0, @hStream)
1527 GdipCreateBitmapFromStream(hStream, @hImage_Stream)
1528 IUnknown_Release(hStream)
1529
1530 If bBitmap_GDI = TRUE Then
1531 Dim hImage_GDI As Any Ptr
1532 GdipCreateHBITMAPFromBitmap(hImage_Stream, @hImage_GDI, &hFF000000)
1533 GdipDisposeImage(hImage_Stream)
1534 Return hImage_GDI
1535 Endif
1536
1537 Return hImage_Stream
1538End Function
1539
1540Function Base91Encode(binArray As Ubyte Ptr, iLen as Ulong, ByRef iLenOut as Ulong) As String
1541 Dim sChars As String
1542 sChars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789!#$%&()*+,./:;<=>?@[]^_`{|}~´" '´ instead of "
1543 Dim aB91(0 To 91) As String ' This is 92 elements
1544
1545 Dim As ULong i
1546 For i = 0 To UBound(aB91) - 1
1547 aB91(i) = Mid(sChars, i + 1, 1) 'split sChar to an array
1548 Next
1549
1550 Dim As String sEncoded
1551 Dim As Long n
1552 Dim as ULong b, v
1553 b = 0
1554 n = 0
1555 For i = 0 To iLen - 1 'encode input to Base91
1556 b = b Or (binArray[i] Shl n)
1557 n += 8
1558 If n > 13 Then
1559 v = b And 8191
1560 If v > 88 Then
1561 b = b Shr 13
1562 n -= 13
1563 Else
1564 v = b and 16383
1565 b = b Shr 14
1566 n -= 14
1567 EndIf
1568 sEncoded &= aB91(v Mod 91) & aB91(v \ 91)
1569 EndIf
1570 Next
1571
1572 If n Then
1573 sEncoded &= aB91(b Mod 91)
1574 If (n > 7) Or (b > 90) Then sEncoded &= aB91(b \ 91)
1575 EndIf
1576 iLenOut = Len(sEncoded) 'return lentgh of the string
1577 Return sEncoded
1578End Function
1579
1580Function Base91Decode(sString As String, Byref iBase91Len As Ulong) As Ubyte Ptr
1581 Dim As String sB91, sDecoded
1582 sB91 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789!#$%&()*+,./:;<=>?@[]^_`{|}~´" '´ instead of "
1583 Dim As Long i, n = 0, c, b = 0, v = -1
1584
1585 Dim aChr(0 To Len(sString) - 1) As String
1586 For i = 0 To Ubound(aChr)
1587 aChr(i) = Mid(sString, i + 1, 1)
1588 Next
1589
1590 For i = 0 To Ubound(aChr)
1591 c = Instr(sB91, aChr(i)) - 1
1592 If v < 0 Then
1593 v = c
1594 Else
1595 v += c * 91
1596 b = b Or (v Shl n)
1597 n += 13 + (((v And 8191) <= 88) * -1)
1598 Do Until (n > 7)=0
1599 sDecoded &= Chr(b And 255)
1600 b = b Shr 8
1601 n -= 8
1602 Loop
1603 v = -1
1604 Endif
1605 Next
1606 If (v + 1) Then
1607 sDecoded &= Chr((b Or (v Shl n)) And 255)
1608 End If
1609
1610 iBase91Len = Len(sDecoded)
1611
1612 'workaround For multiple embedded file other crash will occure
1613 Static As Ubyte aReturn(0 To iBase91Len - 1)
1614 Redim aReturn(0 To iBase91Len - 1) As Ubyte
1615
1616 For i = 0 To iBase91Len - 1 'convert result String To ascii code values
1617 aReturn(i) = Asc(sDecoded, i + 1)
1618 Next
1619 Return @aReturn(0) 'Return Pointer To the array
1620End Function
1621
1622Function Base128Encode(binArray As Ubyte Ptr, iLen as ulong, ByRef iLenOut as Ulong) As String
1623 Dim As String sEncoded, sB128 = "!#$%()*,.0123456789:;=@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_abcdefghijklmnopqrstuvwxyz{|}~¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÃÂÃÄÅÆÇÈÉÊËÌÃÃŽ"
1624
1625 Dim aB128(0 To 127) As String
1626 Dim As Long i
1627 For i = 0 To Ubound(aB128)
1628 aB128(i) = Mid(sB128, i + 1, 1) 'split sChar to an array
1629 Next
1630
1631 Dim aASCII(0 To iLen) As ULong
1632 For i = 0 To Ubound(aASCII) - 1
1633 aASCII(i) = binArray[i] 'split input to an ASCII array
1634 Next
1635 aASCII(Ubound(aASCII)) = Asc(" ")
1636
1637 Dim As Long ls = 0, r = 0, rs = 7, nc
1638 For i = 0 To Ubound(aASCII)
1639 If ls > 7 Then
1640 i -= 1
1641 ls = 0
1642 rs = 7
1643 EndIf
1644 nc = ((aASCII(i) Shl ls) And &h7F) Or r
1645 r = (aASCII(i) Shr rs) And &h7F
1646 rs -= 1
1647 ls += 1
1648 sEncoded &= aB128(nc)
1649 Next
1650
1651 iLenOut = Len(sEncoded) 'return lentgh of the string
1652
1653 Return sEncoded
1654End Function
1655
1656'https://docs.microsoft.com/en-us/windows/desktop/api/wincrypt/nf-wincrypt-cryptbinarytostringa
1657Function _WinAPI_Base64Encode(binArray As Ubyte Ptr, iLen As Ulong, Byref iB64Len As Ulong, iFLags As Ulong = (CRYPT_STRING_BASE64 Or CRYPT_STRING_NOCRLF)) As String
1658 Dim As Any Ptr hLib = Dylibload("Crypt32.dll")
1659 Dim pCryptBinaryToString As Function _
1660 (Byval pbBinary As Ubyte Ptr, _
1661 Byval cbBinary As Ulong, _
1662 Byval dwFlags As Ulong, _
1663 Byval pszString As Byte Ptr, _
1664 Byval pcchString As Ulong Ptr) As Boolean
1665
1666 pCryptBinaryToString = Dylibsymbol(hLib, "CryptBinaryToStringA")
1667
1668 Dim As Ulong iLenB64 = 0
1669 Dim As Boolean result = pCryptBinaryToString(binArray, _
1670 iLen, _
1671 iFLags, _
1672 0, _
1673 @iLenB64)
1674
1675 iB64Len = iLenB64
1676 If iLenB64 = 0 Then Return ""
1677
1678 Dim As Ubyte Ptr pB64 = Allocate(iLenB64)
1679 result = pCryptBinaryToString(binArray, _
1680 iLen, _
1681 iFLags, _
1682 pB64, _
1683 @iLenB64)
1684
1685 Dylibfree(hLib)
1686
1687 Dim As String sEncoded
1688 For i As Ulong = 0 To iLenB64 - 1
1689 sEncoded &= Chr(pB64[i])
1690 Next
1691 Deallocate(pB64)
1692
1693 Return sEncoded
1694End Function
1695
1696'by marpon
1697Private Function lzfx_compress(Byval ibuf As Ubyte Ptr , Byval ilen As Ulong , Byval obuf As Ubyte Ptr , Byref olen As Ulong) As Long
1698 /' Hash table an array of Ubyte*'s which Point
1699 To various locations in the Input buffer '/
1700 Dim As Ubyte Ptr htab_arr(LZFX_HSIZE)
1701 Dim As Ubyte Ptr Ptr htab = @htab_arr(Lbound(htab_arr))
1702 Dim As Ubyte Ptr Ptr hslot /' Pointer To entry in hash table '/
1703 Dim As Ulong hval /' Hash value generated by macros above '/
1704 Dim As Ubyte Ptr ref /' Pointer To candidate match location in Input '/
1705 Dim As Ubyte Ptr ip = ibuf
1706 Dim As Ubyte Ptr in_end = ip + ilen
1707 Dim As Ubyte Ptr op = obuf
1708 Dim As Ubyte Ptr out_end = op + olen '(olen = NULL ? NULL : op + *olen)
1709 Dim As Long lit /' # of bytes in current literal Run '/
1710 Dim As Ulongint off1
1711
1712 If (ibuf = NULL Or ilen = 0) Then
1713 olen = 0
1714 Return LZFX_EARGS
1715 End If
1716 If (obuf = NULL) Then
1717 olen = ilen * 1.1 + 80 / ilen /' consersative buffer Len '/
1718 Return 0
1719 End If
1720 /' Start a literal Run. Whenever we Do This the Output Pointer Is
1721 advanced because the current Byte will hold the encoded length. '/
1722 lit = 0 : op += 1
1723 hval = LZFX_FRST(ip)
1724 While(ip + 2 < in_end) /' The Next macro reads 2 bytes ahead '/
1725 hval = LZFX_NEXT(hval , ip)
1726 hslot = htab + LZFX_IDX(hval)
1727 ref = *hslot : *hslot = ip
1728 If ref < ip Then off1 = ip - ref - 1
1729 If ((ref < ip) Andalso (off1 < LZFX_MAX_OFF) Andalso ( ip + 4 < in_end) _
1730 Andalso (ref > ibuf ) Andalso (ref[0] = ip[0]) Andalso (ref[1] = ip[1]) _
1731 Andalso (ref[2] = ip[2])) Then
1732 Dim As Ulong len1 = 3 /' We already know 3 bytes match '/
1733 Dim As Ulong maxlen = LZFX_MAX_REF
1734 If in_end - ip - 2 < LZFX_MAX_REF Then maxlen = in_end - ip - 2
1735 /' lit = 0: op + 3 must be < out_end (because we undo the Run)
1736 lit <> 0: op + 3 + 1 must be < out_end '/
1737 If op - MY_NOT(lit) + 4 >= out_end Then Return LZFX_ESIZE
1738 op [- lit - 1] = lit - 1 /' Terminate literal Run '/
1739 op -= MY_NOT(lit) /' Undo Run If length Is zero '/
1740 /' Start checking at the fourth Byte '/
1741 While((len1 < maxlen) And (ref[len1] = ip[len1]))
1742 len1 += 1
1743 Wend
1744 len1 -= 2 /' We encode the length As #octets - 2 '/
1745 /' Format 1: [LLLooooo oooooooo] '/
1746 If (len1 < 7) Then
1747 *op = (off1 Shr 8) + (len1 Shl 5)
1748 op += 1
1749 *op = off1
1750 op += 1
1751 /' Format 2: [111ooooo LLLLLLLL oooooooo] '/
1752 Else
1753 *op = (off1 Shr 8) + (7 Shl 5)
1754 op += 1
1755 *op = len1 - 7
1756 op += 1
1757 *op = off1
1758 op += 1
1759 End If
1760 lit = 0 : op += 1
1761 ip += (len1 + 1) /' ip = initial ip + #octets -1 '/
1762 If (ip + 3 >= in_end) Then
1763 ip+=1 /' Code following expects Exit at bottom of Loop '/
1764 Exit While 'break
1765 End If
1766 hval = LZFX_FRST(ip)
1767 hval = LZFX_NEXT(hval , ip)
1768 htab[LZFX_IDX(hval)] = ip
1769 ip+=1 /' ip = initial ip + #octets '/
1770 Else
1771 /' Keep copying literal bytes '/
1772 If (op >= out_end) Then Return LZFX_ESIZE
1773 lit += 1 : *op = *ip : op += 1 : ip += 1
1774 If (lit = LZFX_MAX_LIT) Then
1775 op [- lit - 1] = lit - 1 /' Stop Run '/
1776 lit = 0 : op+=1 /' start Run '/
1777 End If
1778 End If /' If() found match in htab '/
1779 Wend /' While(ip < ilen -2) '/
1780 /' At most 3 bytes remain in Input. We therefore need 4 bytes available
1781 in the Output buffer To store them (3 Data + ctrl Byte).'/
1782 If (op + 3 > out_end) Then Return LZFX_ESIZE
1783 While(ip < in_end)
1784 lit += 1 : * op = *ip : op += 1 : ip += 1
1785 If (lit = LZFX_MAX_LIT) Then
1786 op[- lit - 1] = lit - 1
1787 lit = 0 : op += 1
1788 End If
1789 Wend
1790 op[- lit - 1] = lit - 1
1791 op -= MY_NOT( lit)
1792 olen = op - obuf
1793 Return 0
1794End Function
1795
1796Private Function size_comp_buffer(Byval ibuf As Ubyte Ptr , Byval ilen As Ulong ) As Long
1797 If ibuf = NULL Or ilen = 0 Then Return LZFX_EARGS
1798 Return ilen * 1.1 + 80 / ilen /' consersative buffer Len '/
1799End Function
1800
1801
1802'Generated by FB File2Bas Code Generator v0.80 build 2019-01-05 beta by UEZ
1803
1804__horseani:
1805Data 7,1,18722,5607,"Base91"
1806Data "86Gtzzbj5xkAAAV/(3V*[51cw(IAAAi@h5ot&+|W3iAAcdKB%1f,QIL%´u7yQ´/B5wrN*hwWF:nN3$(&tE.o.I.2H?#Nf49/k^;msAFBQ´´+k^$kZBdEIoMSEtV%5EN$kATPKCvLDXDAYLDX$A25iGAA*zzIB=RT1T:|iLSKFHv(0W$AAAE´H7TK~FWA>´DtBAkAdJ1B*XhtiAS/yAXLzZxtBAGOgAC´=JE)[A;C1B:CUE[h^XqWDBCA~~kB=CyWeGZLH;#AeAh={EOAQ)6Fn40BhG).pF,T>>NCVceu)BdR|Gx8(nEt}F/taL46nDLEv(<veAwA´v0)tKA_%Nc8yK~F!sd+63_Hjn^s/VAGBwtWz(GOjnK&WL+_AqiS?L4IrP&T4}{FVuXLw/´ExnO+kNqC)v]Xd`,FAD´u@8%`eW5%AAZtfA*`Q*AAfnA´{}I`jUl_0[zkA´$~4B=~0~<vxykB}a?zZC1(U~vW.hJVv(6´9~W|9~/CY|k~4F_h+>^Qf~.vt*FunI%hMs+>F´PAJP[O?C`5{?$TSa:FVjkk@Q<r0)|Oq<WF#fsc)#HAK&aF911CZF5We,etXum?{Jl*6(1K<WQq;)7AvUtu.t´~xq^sL71+r_9W4M+_>~R&A%fZBtHA|^iq$!{LHJQtqIoBp*0_>>>2KBCwBVui+Uh|NhMs+xHLT|AfD)KCCq$A>K+>i!At=~+~kBe~nEA!Z}0[gtYurIAAuD|ec)$AOXv(k_´?mBWL1F/CtIYAJC;Q0sv{B!FuiBm>fAhB]K{e´mhsfTJ?7llIPfaFm!wD,h4´gA}Qu,sw(iuA+>XRC:DXLC]Qvv8tF$~vBixtDvlBJV0MH`ry#}~(L?;v/C*,$~jq`%1M.oRB$$Of]h)H99Y~yw6)GApN)CAsEH!KDCw~m914j´D)8A6CJV+>AR9qv(AAyvw(ni*hWL=JtWL(y|E%Hoc~,o3(OCRd(|>PUM@BbI`K(HlF{3XxB´*B"
1807Data "gZ?r[@ARFuhI{&p`?Q?r[@ARFueByKk_BtHAA´BtHAeA*Josm_fA*7`3]g^P´$~{Hu$@C+on!Gw03P2v#CM),>do$$=2^D´Q1hP!(*MBt92WfJ:haqM@cF>J]<c?,>Pw,}m?cFF!Ag`BmGwdZ%k=e~qy2WyWc4´Q|BxWs8;?B´B)0Ms]Tqv(DAPA8A!2D)8A@AJ`n+_TBtsFBL/CGL/hmWDA[d`EDACi)HLf5V%DSc0RJXY4`RYgN~~~ARFuhI{&p`u1D)QErh(|nI!Kk_BtHAeAdByKk_BtdW+>Iz4FHT%trq05Bt}_tt#UPnkA2(Re.MD´U1iBQArISi(L.T[9?(=p54$g__oFHA)uJfy!k=6~qcUU5B]knqA*AY_K8vi5i<HiwpUZVB,D^p)tLNofAqlBPXV´M<)aJ?iqS6Xh__=!^~C)&OfFSqv(DAFueBKCXL9~aA^~|s}./C*~^3I/d+4;{_lXLC)cfDSL0INDF´ALsc4OsEMAC?r.Xq}FgwWEtWv_u1D)QErhfDzHW&|DIAAAlBEAwAAQGABAi´C´oI,(uWn|JCgA`~/COG%tXLdQ5F.B4A&E~CJt~LXL´UGHk_znJV4AjnXZyW~EP/4AAA~CLvBAOYMA;Cot5W.^&k{G´>*_OA,>5_=pWjj?f´@Q5F0KE|.FuK#~znNVr?ktAw$}P@+bdZHA+>=pn(@J|F$Fw4SqAAO+(ACttB^L*(wCB*SXm|knv(lLcAR14KN/^wOVFFst;CDtc~*>T)AAX^<~xkB´kBO/A´cZg~B´Svx~B´XEcAhtVE]´mOODNta|DApF$$aL9~?VD?#AOW`~T)I`At=>vIht`hqY^*T[.´JC!MiA$AC´vDEAuW:C1[|LoYUtKt,hAAJA5FwAZ4H´TXsA!kGBBtVRcsHAfL<~6}EtfAqAyKJu+x2WXLRAnLlN@CtdJc!(CBGe=7yKdVj*WD.W1b&p_UGu6Fi63WyK´EC´=ChZFtlW+´iq"
1808Data "BVK>et>Cdu[Li_ADo!?EE?AAh~BGE|d+|4TGBySc,L7F|vQp[9&mzDx?mum?pYpI%BbFVwEp*L(nvS2Wd`^|=DrB1zlIDLAAAA3PkBE@B´!hA´x:oBHtY;B´:vQDMV%~3F7n[t;>}5`R9A~hQDq(>Xv{Mc$@#Mf|MJEf|(a47hN~B^u(Y}B<D)!A&C/Vk_CtIA4!e!/>WF4YBCLX.(ruDHZL3Lr(0JVX7)zuDHYE.{Zh,$`C]U1B:X[tl_p@h)tK5f=sMRF0B^/4Xr7LMk1KXLM~{3f(wQcs,((B]Uyg´e<k;&T4Eu!(YVX#Xx&tWreByKk_u1qV+>RiB´#}k4no![B´ujNRGOyP|L!G~eAAn_`fE)+>k~.vu1*o)HtIW0lIxh(|*,u(p`u1D)QErh(|*,DAPA~~D´HAeAdByKk_BtHYVL^3bv*,TdNC*Ga!A_9(Lf$*_)1pi:D)]p7#1)Xx|E9~*ZQznEjqlW)@e5%ZD0DAKvRVp*pxzB+2*,B_9[ln:>);BzZ4=V´S}J{e8}cX_={gG>6g@Q4^l=ZI~J_|kByKk_u1HAYAIYOiXL~HJV´~/C$~_~^yv~;s4A3F$IlBW{n/IUaE_EqHZARBp(tI])YLqSFuhI{&p`u1At[@ARFuhI{&p`BtHAeA`~DAPA8A6CJV+>,sFu*km~>FDHQYH6n´#CNJY/y(KtI?L`CbFK7*#FO7U.IP6]RVQY$mh(#T15+^&=BwN/HA8I=VnhMw$P!A6vFEmYBA}ICY8DxnWuk~EN8C:vX6rFIIAk;f}>ARPA8A]6D)8A6Cxd[@X4EE9T9~´~c?3}MJHRvDB`c~knaOhVaB{MzwY@Q),Be?lu,sMcV%gI{&p`u1D)QE(~FuhI{&p`u1HAeAdByKk_9CJV+>D´HAs{]AR9V8AAGA6a|;,>jno4o_#^OAh=atyChBggrP*h]ACB;n[9liAA:XGO,(J´/>b]Aq`%Ety´Vq$AzvRV2KXFkLYB+>"
1809Data "6~jq<)/>%AsIP)$~Bw_s+CvL`p´XuK|FXO,TEt!~znJtkty(xnHA+_l4CteLL`AwAY:´Jw)M}gOE>wAY3KGiaFv1BDPjWLE´B´XL#(4}]QC´,}B´myS|ANLvj_n.>~@~a´@~KL0)B´eL$As~eL_E4F$AKCpIqykB:>h´/Cw_K?a|tW3(7_AthBSu4FxWXDBA2J/2^}!F!WRDXLAARtBtKAIACt8W´e@QHOTAGA1BC´oIQA:CtT%J<PMA:CHB}$ot!AfBWu;CwWPD5F*hFBtW8UnBXLZC8FFteGbLOWT|4FTXBtYYO8]_:C%Eo)^q*EWuoB[>dBVBl[9PbBW>ff`F´C$Amq:CcBJ>$^=p{>lF~>RtHYK>%_}C?4zC*T[sV+N>h´=/T?4I.C´>y?BGvWCw7cU_AwIAzwWEv?,B@FpFUcu_I?iqo@V5l´VZd}gA&!FuiB2eJC7A44X}uIz3LC]6Bt!]&~sWF`3}Jo%`S|dGOioI4[c~BA%V,zqEI´7vnGl(/Ceq~hFB)s|(=~B!FulIb(Y}B<HAB´v(HAfARBv(PaJ]HBdtqkIr%_RMHO0H_E1[X´2!3pZBnDC´B?FCC´7)8tHx8A2K|F7vAuCA6vtBbF]EcxwwN>KH3vYX~=(_ap%Fr20^44)UTz~ERt´X^L;DDqJ&5&2UD%A!F´R!@yisI)YIJC1CTXspmLU.u(fAj_rWB´Y~NWyK6},}(EWLQdJ´BAo4<MvKO´H_WEL?zK0_lXLCOiWu}]%6?D<<D)SE+Q?r[@ARFu{~BieAdByKk_BtHAeAdBd~fAt[~a]/TAMc!}vWmu;]Bip1}+y%7DZX};`>Pz[9a4|O^K&T3z*.VBUEWH*F5Cmu2BZl@v.t)MQE&]jWh~eZ?vsP!,?K:vYVXXj6ApCXDH[h@jzJ:>}xBM}Qo,`EJ42bK><?:v3(<aDMQtQVtW*LP(Xrv(DAFueBvDY4)qKSNLGAku6t)~#TFO<~s~|@852~t+[t"
1810Data "[Q~hrb7`~(*hfH&qAYB~`Ejn2FvDVD`t(a0sv{u1D)~~ARFuhI{&p`u1D)8A6C4}#A6CJV+>D´HA[|ZbL8N|6z:+Ex[gLN]´NFW{Rc&NCYqC´i?:BAcx6WgFmq<k:AhgkBbL:CF^K&uP~jMt:C,(LCQSrIgaL#´s3}WL1LNjCXG>Yl@j5H´t_TtIaq/Vb(t=:T4}~@&qBXz38iICMVZ~VI}8iaJ.DAFueB=Jv(yX%9.QvP2rB´RiAA%`H.^)qW@~;wvextY@lijn0IUE)GI´y|2DV(Y}^suxB´u1D)QErh(|*,BiIC(Q@}#A6CJV+>D´HAeAdByKk_WL0/7cCR)zv{ajQc^HfB1F*ALFr4v_Y4vA8Q>U~=#´OCwW´hQ´bE4A*k<If(BG&F{eDC1%Tn;V+i4qTnfDyDQiA2PAg)sBL@a=74u1k=:/9(}6sLAA#TqK+_4Iv([FC´A*7M0E3r^)*KjH.o=BaA_)ZFNAVL~FT|j_8~]|nWd~3}A/tW0[V´.Vd+}sp~SVd~[}#}J´5yMJoI+hE_.C:KLCO@PAKCi_gt!~@JqCB´a|d~4FJi/`9~$~0[9W<F|Bv#7&h.EBeZUAC´AA$ABA5FfCEAet~9*hOcoIBt9FBAz(lBBt%t}A`b^HDA%ty´BA[9+W+A9A;(&´:C.A$AFBW|$t^GIAyqrIfL$A^C#(fAb0Btz@.W_UOIL?GuZL!AH*Gty(&BzW+udADRKu+H?WaavD4AvDEEz(;C3nItB>R@}C`%li#GPt2(tK+_CqeuktDA2(1K+_i|At?J|x]C#r*V+_`_`~|EUBdBu({LLFAwNB>>2F@AzD*n9JIA+>BwXqmZAA_U0M8GSuBV%>fc_Xhq#?C´lOmYTr^QC?8~A´M/8~JAa´&~,}e?tW2(y?inVL`~DK_s$CN/q?pIYLL8aGa´p´l_+h4}QL0´9~IJX(csMcz,9Meqi´>~YN9~Y|BiB´B<D)!A&C/VXLCtHh?+k~Mc!/"
1811Data "<C1Dj5Lyc4Qg[ctRz#C}Dz@J_E{>C´gLZCPt]L?(vDuo3tOEUBAA?rfqC&tW&_s_]XO8D´vrAMgG>~mWbD]_3FD#7yOEaCb|<VeAUcx?yCOAD=}FFk,>p1NW1gGOG>BGEA/fVvkB!w6BMRGLT|u1FArs2()~<~x[M/<JV[*>j_`~&~ktWuWE~~%~HUk_4}z_]tqB(LGBqnBtL/6te~8F5h~l6[Yt1KC!~*#M~}JC}~D)SE7hN~B^F´PA!AqCd~q=8#4jHCwA[A4cVXoI#@EZ1)c0(Co+@vdZQ^jnjOXEE´s´7*0SS&23%F#GqryKd9Xq0BM@D_i|;X*/SE=pI*´L_KAtW;_6{CgyQp>JsIIL´QGB*rxC3(^4K*Y){@MVz/U/0(js~flB@~a%HLrFSqv(DAFueBUEC´x[M/YFq1´3yDI´4~)~S#M/4F1R?Qt(p~m|j0_ELH<AAw7(RiY4pF$Y3FQ´P@Hi.o/ClBMA=~>M]>5FA´´HQErh(|*,BiIC(Q?r[@)h&qv(DAPA8A6CJV+>D´MWAA~1cV4F!hzXUXgHWbw1$Es_on:2^2?6SI?zDdYekX)TqKqixn70vxTq|v]tji0,7v3(q?$~qy%C3|vtk|:XAMi_Ai?D2fSC0{&y:>aF9D:[j=´iKvf1k=%_(qutvt3F@FBY$&?PhFSqv(DAa|*,DAJA_}]|*>2(3}´3B´VL*G9~~~j[]|&,Otd+:v}~=~W|t4!GuZ]&aGI´1W[@L_?G5H[hMcu1g(B?ARFu{~BiIC(Q?r[@ARFueByKk_/CJV+>D´HAeAdB´Su{?>&,zWG´fB^7z{3Y<;uD5ben>umB*h27HA:&VxD!YLERw+NnwDgy<)SL´YWRaU2=WL}Fb&qH`VC´4kBtVM$H/N}F:vZ&)MRlYY&M4=F_Aa)u#Ai|I@WED)IC9C3r9A6C3r[@D´BArF%{jBU4S|b~)~(&F´Xx}~`~2`?@UJC)=~:V~hmWu1m+49´Qlu{X"
1812Data "G6FBn+A),f}´ZSXL|i3oi(lBAABtAABAlBL7AA$A$A6A6!C´qNoAwA8MC´v(QAPj&F&aAAd41AXL=h7?BAGO$AC´=JzXlBTJeGXLoI,(5Fo(:CpF=~4FvLi´dZFt6yN/^JrCM+dB`EDnNpLVZ`D´2Wj?DA|Q<4%TzZ{u)a>W6C+Th=lhCq$$DA/AYA7PLVyKZF0n,$]L{ytJGB8A8vS&.hxDQt3(g~[Kjq&CkABAC>WLBw$}@V$^?T(vc~,_6C.$´L,Bg´DApFl%]LcA2W04&^xtB&,A<hBt(Alk+rUq%[<v`xwAGAC´G`M*>J:[J´AA;dZD4}ULOW8~}~@3S|Qtm3M/M/_~RW:&@~m|K?/C:WT)HA`~&CxBXl5F`hJV{ev(EATLrnvIqW/VBtQL8}WL#(BAj_B´VL)5i~6}C?JC/C)0`R1/af0W$O+h9IaDF´?h^Ca|pA@ByIKX*EMcm_=J).=p4k:C`^Aq(XGCh/qC<)J>F_,FT#%LH`=s<)hO<R=V<s,v*,CqA*_JA_5v´X1UUEv(xXaGjH&<McN~?Kk[#%CT$_AwcAII´CauFuo?F´PASE2AJ`<~ink_8~{;t(B´$L}s^~Yt,>+~HA=~}~2(d+#ANB5y$t|>bcxt,>uL+C3(a|fGQ&bSGH2C*h<Ca´i|B<D)A´B!FulIDLT|v(HAfA7H/~W{wOHwyW44}Bh{)lATx´)CQgnA[´j=cH^>|!wKM)@OGAGu8v´QHr8?j|?B*&~(y_$}J´bCA!fTLvSqZ&Ih<8ooK&m?6~gqB)m={FLEMO`5=@lh(|gByKk_BtHAIC9ClBY4h´~~*>3}AtlW>{A´~~Y~,IGAJVA´%~i|$tT)?@PAqW*BgZ1Z5Yv>[teB~h#t/OYA~WAR(X@j?9Y|H"
1813
1814
1815__fblogopng:
1816Data 4,0,2514,2818,"Base91"
1817Data "vuk:eJs4+BAAN/<MCG4DAABtCAAA|FGAAATX!aQIAAY4FHa7^`B´kBAA8s3}U5lH%k8)+9@=8~VLH?|LAG{%B>QhmoM@ohc,Q>[*FTc%*M7LGxrg,`L4rm72<:Wa{ciQ[nzi$G]zFK|+.^gkf}h_R6FNO`2GeKC´U@Uw{Wo)/eVSxm,cCUK!2qE2gFx}.VE1pw8t`dD0^m[z_^xhs4__^K6z@?8_o/P}vhp8d{bOA4VVoP%Zd:lG{7JqWT)st|+>5DF99;&P|UvC||@_mp8F/_Rb`IRLBGw?x4Qz_I|)j~mH8eSivTRzii,C;yjR+$^M%r}CVcEN24Q@CcdFZyLNS@k´qr{EA´Y)M=fQRDD5K>pG.~+,´F&SNavC]qN´H[U)9v@1vfGaK[&BN7f[vN!Zxa2RB_9[YwIYPu}qA[h.Y@U6^X!`lZlhHbEgNEMKtbvLuS<yWpFg}3q5$Ub+$J?2%35:,r{3AEe)^b^fgzKe5aY8E;7q({C${+g[|rc´5c2E´ckE5^Sje#MvdU>(|_[(g<K2>Sl2iOb:3SeGokvDt.R%IzF[mMw;%bevPWr|lMg%vp_MW.caLDm:#T4Z@JMwt[@I0nBM&jnkx%<IP8P3WnI~3H´3MK*N=qzJ5IxN{ebRYm%^hMWtTmE,3(B76Fhpwt7xFG.onS/58YTLKuPSBzYqWvL)(6ZH6@IGYHcx)/S`t8vw&q)@UQ4?<+mBYd/~V/G6C6tZ#rGaDS>c6nt=$=qNF9y2^>wC&5V/78~/fK,#Lu5maS7(!Pb2´PnR{&lZLh_@j´!n#G}f>.2HzUmO$i>#N)ixF*uHzqHc9k@]`nI8eWctnnvs*FUNSQSd7[WO1iaL!QLCW]{Q+=/wJPN)dBTo{DO;#lzl?r:RU]T/0ZU+:OZ$"
1818Data "K/V´;WCD806gh5(6mni6.Q!d4E=5`6du6CBz~(d9mB,gLQh0_)~^B%;´21ER;Iz[/W_ktQ<3FN5NF2.>EysUSEwG^MVq~DQ#wOj~^Q_%k0U/^0Szg]hJEMZ3A=´0Z|jj,nW:H+t8b{b[aQ^k4`PLAj_U%J6ebGaSk@k4xMI2>QQ%3?Isfj4ImN;l`a^d`3QIWZ88vJ|^hJPb.nyH.f+J24>=K_MNPJ.%?/XQuGK3bGRx$(X~Aoy>&P4p2V/x{[p9Y<)QT}59Ai20xMR$Df´aGYM%6<J1[%[:%DH6AE{/o20YSYZ8UG|h*7On]8EMBQW:G5P3lJ{[FOiM^@[L[+>v(C)F´3f´jSK.|/A`IE@>>1uQyaKzQG10Q/0WFqqGewkL7yL13!<WN>1j:*V[^a^fZO^93psWrYbvwZY~<yI|2Y$F3ZdCy4*NB<4;eryg^`YqMOZ2TJDLgq[toD{9{Kzjw?([ll*J4Ej!OMxN2k.wQ}QTn6_P@>Jb4UY<Aw&r:OQ|62DS8:H2*n*Xc/i|)^P;O)=$jBXYa/2[T!#DMfvO´v5U?K6yR9Z;8WCEA+!do_boYgmi(/0a[N5kg~5MU5qV/?kU[>zoh)|hGFWqb@ibl`UJrysuroJe]Kbjo1suLn:pKI8IJ;DvO]`rQuuF?oGmkwHV`yOta^v1|QIYEeAkago&>t?wI)~_v!cC35q`d0,!z1q4e(H%(1DqN/KOXuhCQuh`c%MVs^:_2&i^jQ[{x5tL!U´}1|emgAyCp2Lk(||BJf+)Oz!(;YF^eZm>~FX@.P<:&_n`N_FtdIzDx&/!QOaV{G|H%j{s|>ea=Y#PO)rJ|uzC88bW6cvT7@H(}cSj}vVW2]Rh]7%e+Q[6Aab+2_f$]I.zIU#jN.sGRxhzFenZqrr6"
1819Data "81;NxCrYALmq_bu_IVLyE´!QpVI~@=Ks35:97}LM#p^OXQ&LMc9t;MJc8#>o.qCc>A´bKrTc~<$Wc,257k:]`{G4v+%W]RCp4.+{Zlpf/:o29;^]|Ks]5E8l?(F#x(gxtaFFG<u^(KLJ95`(GXF]95Z[@isHJ=[Jo?D@FB?DJ´RmcfrEJR,$q<<B4o`$q$3kuOBbQ#@@K.VN](Wj@M$F4$cvJ_dy?#ha.1e_ta4O)sb^h(75r7`.KE´`S7e/YG2e&kvqb24]l`I=H06+%!t<<5vW,oV]=s6zId6<BUqY6~+oX@Ph´#dw5%dd!NkBc]6=4]?ps/0d@Z(1^dcpkF=4L^1HtFT0&U`>V7i(WOFa{aDI^bDj:;5SvC5MhaF0aYLiX=cB{hOJN*F´b=I!.uptI?32/t#*PV6!0cAIVp|bAss#9Nc`2WYwETn2JW1BEP,m1~ExF%&[cscf;}VABi4L=N$LzD{Huy|9{>NLlW?´4OPJDXP1EYQl!J|XFU7´#`len=^Er]OB3hi?V)q9iDP?$@FB8D4q$zb*Z[Pm!aipxvIVS+@l/)vdn5]hR2(´6{N!Wbu$f/~|5Cx5sPQ82R9/4[gIv_z&It,/9ounf>A$r,{mpr~_E^bY#Y@u~deL=h(&7w|9Jlc!,m3$l<<Iti7aP@H8)N:nR/YC]cw=@_]7d?F2J*:&(]+.IZGPO7uWd´d>7&%fr[=v1:SkT+W)B|~LkkFO+$8%/Ba,=VQv};DLkG>T*?eKI?JbliN1IQInY==I*k4K7.y4z9fCLVN20OnQD^CQrbtZSclZM7[YyUS0Q.p|oR4C,XndOOSKc1q0|9&,=DIIEg4I8B$fnj:il4BU0G@kp^QnvEz;kz.TdB(e5)dE?`HFCQ:6,>VW_RF5De6E]S´*"
1820Data "ovm<#^^^51ul^!&i1o&=P/f8C!iAD/3!C1(2:Bp(FPefe9wgpJK^O</:#G)QbuSS?]A6^UCMa/_>5grxt(a,dZV>(L[vj0sh(GLUEi<s@x:!?2]m.ln2B44+0L??=1}J!p:R%[P+3Pdy)5$EQ~?e2Zu,<j/QbUw/&R/*ACW!6yFusf+d@vDmo$YeLP]Xqx?#1z3]0u%ES<]80B^e5jy0f6dCL9AD!)xvR~F*cTK2qh_QK$0?G}~,gT3wc_:aErk,ygdYY4Dg6U)_?ewK2}2$Y[gbv}8z4@hRvFiMR>qrBl[l7u{/DjFy$`$^DGA,m7Ja_~Fw@s{qEID`~Zfmm%dWKyrVX#H9*`o{E(@e5]Hs+9V;(0/[O).]hVCCAAC´nHpwZ9)´&F"
1821
1822__outputpng:
1823Data 1,0,664,741,"Base91"
1824Data "vuk:eJs4+BAAN/<MCG4DAAuWAAAA9FMAuWN/*~zrAA6y#TzjGFC´cLCA`BOC1=3O/AuWCaFM(F4n2g.+34^ONHj~!=dN[;dHIGJYkCziSJ`0K|AG.#[v$BfE>yjpg2|vv#M7qCRQyw,[*B(w6cmK0iaK*1iQ.+:^v/9<oWlQ4HzzbR&sYyqzqSn|a|xUK|G&,.XIPtiY0Sl64~iNJ}`o6~K^&K<q06ORYLx29]`f<ndUf2´[12lc8xnuFkrS*Y@E~Kf.8;B#uSro2<}:svTQ.,/pv(zBY!+,´7Q,Cw4QA.I=E.86vtiVtO´/oK]o~!NkiXY2G´Q0t3siXAHLo~H/ICjtvAnFJ`)g_~=1x}}´GMdK=X*sB[&=Q4[/BJ&F`0A.y9B(,u5dASDAOfcD/7Y{SA´Al%4~dsITZmR6BJV0iMC´}Oa>v(`1Bo:C[sB`5Hp+sr[@T@i}LBAk`WpREB^aRfBFBtbJ4[VAp1:9YLgj55!bC$?´kMBt*NFT}/BJp:BRmrFrY_M{P=6b]|%y?=Hov`k?w9a=t$py[joiv/K2!Bm>XLR´{}*Ai0@OCxCA~d,K_V|}fB+{424NN.*tX>iC2k/6ISI2V(bp8df$AA(A5t)]LA+OoHxG8O#@lk`iVropC~}x]#a?RFrRKad]en?(KBdZ08f!x=?p9+AbH)vgI]E~6yvhu!nPoHig#,Y(>D7F#{_CkXyB|onM7GC$+#CeS0of1mGd`7NnJm,9AH8%SL}kuE(wxj<@1,n}~mVw;3rWa%[DVsIt[VwbpXH,9~I~~Le|0;xS`aSAAA6yQMFGPe=hnB"
1825
1826__compresspng:
1827Data 1,0,614,683,"Base91"
1828Data "vuk:eJs4+BAAN/<MCG4DAAuWAAAA9FMAuWN/*~zrAA6y#TzjGFAAsxAAJ12Bx9iWbBBt@QKYrLV?R%TzgXTYzL&}}=%xKY#xzGrnb{5L6kB:Qo8CG=J0~F$tR5)_#LCFwbVX`tLPVDRVBYoHHGgr#!899fqYmHSXcYl#dv>o^u6OmR>%J?I6%5|(vI_sv`v`2r~J!1&/&Qo<`0Zi5´H+VPjQ´ndgQEsgiSn)ZlV(l`JnD_%Aae!|J~gh{4bLlL_O#l!i>YC2Rj?0]J6%xn9*u]9C6srv`GFE´f%B@A_FSfjRz(kLZf>Y`uCS]JVpfdN!QkGVbz|s9(ZtR<~e3BC>y>swZ4%KW~df$5SD5LBbRw&s]_w8$P;@=l~{&Tj4z2laN58ESq7W7F`=jf:3|ITX_jA3s/7q^[J4c+ixiuYtSTX{wMP2p#QEuja(gO9^TrUGdBXrHOKC$=X^_MXrK)ahrP|;9bUHVEs~bo$$q%|Lc<p$XA´=&yh=1TjHNJ!Gr3)2$jixXcb7@´Htx|2N]ntgyO6ZCqn´~!:T9z.:EAo{%h#&YXC2jUWaLdj´XAM`SbRH7H3;Q}9R6Z+e}X5OAk*I+GWG#zcTKp^(j2sQ:DbJeO2u4l+)TLAzFOm´0BD//S+psTL+1t(A8~9OIAOOraEb)fO0W6SA$B**E>ZpE*<SXBo40coF´Kt5G#|zD,w|a23V3}RkK1b((A1<R4_z.g~&{POq/W´][tbB}EAAAA(d*NH%_C=t"
1829
1830__aboutpng:
1831Data 2,0,764,853,"Base91"
1832Data "vuk:eJs4+BAAN/<MCG4DAAuWAAAA9FMAuWN/*~zrAA6y#TzjGFAAsxAAJ12Bx9iWbBBtggLYrLV?R%9ckhHp^T&oc~6s$?aUDaeM4LMk<6iMZ}q)ofiIrG)v]O(KpWss&w.s{qz4${PR{0q>a.eIQx}h@/Jz>Em:l}z%T_S_wVy28{LFhB4=(ojU`2W3uuB_,Nby8x57Fdb;0~q10S?F~+$STAT|FVG#o~GOoj):%slBYV24Ae36l5CdB8RbqwOO;)90B3U]D/<^)N!%1Fx=c7A$VaDaHGLM2Bb%*E0QlAi6DGBK@JSeCGBK&9LsxxuuK(}%ZYdfrF[C[(JT:D/3M{9j[+!]D´R|uFNb&nC|34yKx!R;M7b:<G*hNR$QGf7fq{G4|L?J=TNdl#NAbB;1z,a[wIADgVbPfr|<nB%m]CMfDz6xm.phsB*h.C5^ek?.##x*4w.c^vR4jU16´0lT[U#nO!7jgwg(UEgK&8[h(.M|ndSTnW_JBX)/l5/9m9M![c_&k$nflgq!+x+mB&=2y40@5oheeY&.?N`CX!.t&o&%U>3L#fDmVE&[y4XH`|=FCmR@bIHiAMe&<@)NNvERCS+$KpI2iMS4&syVqpM;P_lKQbe9Ls+ly>P@`W`dxF2.,!20R$[#;e0m7$v`i_cC[9$[2YUYQJu.x_xQ&|AxP|IL_LC´?It:d]!Bb$!uO=ND</x;Z|j!jv6b*gqGx1I{0Af+(z|e<fyW0EO,6m39I9g2Nb|ED6@P_jf}BA4}.CF%;k.FDd=n?0!1NbI~PWP1/m</12O`u[M/IOoHj$7jJ,z#uRceeyrO+ZW[c^2C0m+vYBvO%cCM.OmfS1v/0I]KVLi´TSd;=6r.HX+´uu+xhEaE/>9=Z[PX&%%H&%T%yfW[PX2."
1833Data "aJaE3^!@|**}/,p}%42g#L7AAAXLhYKMe8#(>C"
1834
1835__exitpng:
1836Data 1,0,540,600,"Base91"
1837Data "vuk:eJs4+BAAN/<MCG4DAAuWAAAA9FMAuWN/*~zrAA6y#TzjGFAAsxAAJ12Bx9iWbBuW>2LYrLV?R%@zsfbYWO+}F2PELh%NUc~4;P,3*?)U?k|>ItET.6?D?CSE|(Qa:K[S!U%L~8*lSm@D|uqBUDId.*.O:´?v,´%O_pGjVk:%9e7KWian<2K|A´Dk@f.#AwxlADEuWO=itt+BZ`ouZ,$IeEQ,7&(*FpnudDk^{4Ak3<jnP,$I7Qbn7f?00A2*&dH&qk9e5SiuBhu´sqF´G1|REu/l#9,Ag{´Y50/`´Yh]7f{1wYQ@Mz$Tz!`T,>90$JF´Y+^XkUWMzN))%Xp|pBlxVIUp>p[!?!a9!q!$T`r~Z5?_outa~|@T&R^l,ocvlA+P_L5q[C7P(!G2+faO=i#B]E5Ni6ghI45|i12*)bO13GjX}AlAAB[HZ=M´0Ri}4rkn4Hn7xt~CcAPr7J9nT[EP1Dp1/@<9W;(g_FskH$+hr2pM,=Euj_T}7tv40t={F4cPssvG#BXFGWu2B#(ut;u}&Hs;U6+1`?c6´wv%CcPlrF&5?1{rPj_S>xDWbq<~%B%aq.,.}j%Y,452d%$Ps~Ot$B+Iw}Z8+OF7RBAo}}6GMqG(af:lG`l/w^/>0~_=3^svCoPAAA6yQMFGPe=hnB"
1838
1839__bubblebazina7_24x24png:
1840Data 2,0,886,986,"Base91"
1841Data "vuk:eJs4+BAAN/<MCG4DAAuWAAAA9FMAuWN/*~zrAA6y#TzjGFAAP0AA@w3B%Z+M6Cv(McKYrLV?R%Nz0h^*BU+}r}o&taQ._GXxNXvLyfi]pS_*3Jd#7)4?pP4/[`c#8kpW|r^1^3auhcvzifGH´TXX{j5i}+7ZACmSHTTv#!a82p=fq[T{ygeN}=Dsai#;)&_3#}Z~u[_;eHAGAAhtZOCi7vAYc<%.2.´pB&DBAG0w9#wPX?96Ua}X>]}Y|<a$HiE)e,O1zYy6xoPRI<Bw^Xr(fdaO#QvZdFAwHX16H2yUK/BwP(8~%G|;f;W$3t@OR<kob67Fp4b:fH1wfh<;r6,NbcB8Fb3}T4#_7v?.%jBcGr35rI,(%CAM*d.+Q(8~dOgc:]y2aEwp&tBde9qJZ[m:2@^Kv%gw;a.cU]6>4Lae|],sZ%h.^GAws<%.7~b1?}6hc~yo?!5/%PlSfHN}Lb0Nij@+]b?1COLm|?5]$e{^}mU~*e;qbd4%!Z´ocV}VXmy<wybjT(/s3}jc.Xc=K(G`ryYZ16|Cou8NU@ubWoN#EA[9nfMV}VZ2kmAAwwQ{d28=k.+9i3NO)ywNhWXlGr35=0qhLlpjynWuKLH?^3.HK^K)cF4+Zko(20|aLHel|]x>(´&´X[VW2rNbRm,qOlN3B2B.`G1wD1x#Xn/fTUedW|ODuZzS$3O%koUb16QHI,2)2O%jC1]CgDv(:voh.bag|<)C%jM|wZ._R|2$;U4Lgo.jCAh=^%>;B_cW´.sh}E_Jc~1Igcpt0PS<;uxDE7+xLm.E%k5NOv?m?!:K&_?^I@ryTJ`onz~[EF%kHzL)/V{ra)svs7B;ur?Ry|W+Pg>MXy>WW>h>MW:#E#o<g2<:S+G9~8.r@qaH1wE1`w]lvX{o"
1842Data "x52@A/{rp0nZ+f@!mlGxBVY`:>/.fs<;I~=ci*6f%/Ln~d[<2<%.N$[#jWD@%Vm9,s_1%R^kh81&+iq*,EIH)iht#^%Dcx{LCU@)Q%V|7eyH%HAFzkq*vJa.e}?G*M3*FT~n,!`1B+j:r{.2LZrUV^P+q7bpsrfX>O=+&I>3(&|e]KAAAA(d*NH%_C=t"
1843
1844__resetpng:
1845Data 3,0,1770,1978,"Base91"
1846Data "vuk:eJs4+BAAN/<MCG4DAAuWAAAA9FMAAA]K@~3IAA`9,KL!/NL!8tnbRnoaDg,WR1,$ztoEIlLBAA;<.#D17;l)t~Je@0?D*_goT#|pw1%sgq`5@p(brd4NF)ZL<oWK|7S|d2oW15>T8js.lCiray~QlU2EOjM2P]}I$9BK0Juzq^&kB*Q.L4jp)rU@Q+(TUNGr2g/@uV$a*k?_<)oP3$@*/Qvi(O^8b8:S8/#,R#`;7aW13h9mH?PH:`<#j93?VqO|p)`B;(Y7J@H]puCwPQdTosz>o^2QU>.]o>NwToZ#(4K<1AQxq#*NxYU>(Y?w&.=}NF#,w|v[&ru;%rX8}%lS6_$8{<8.8j´u(abPx&[wtvJC]%vG7?BQLB0HI.I0kY!5EnWzkH,5=7Qp1jQY(gnK(l/8<X>.yUd[NcDr7S3CpdQ<VqJBqRb;b$/*>E9])zde*L/5_W=k~*7wlP!~S,T5t;o%oU8$_Bd6KjPRVKn{sRKAbl_VpERqb7fwNKEB_IUcn=myCR7Z~O4uOw[_o.hxFKg]´a,ymfM´xuFQlROC%TcwUj>h!kDMyy=(FG2g.x>A7y@oo7;h]jMt09];{@*/Tf6/9i;fXLhZ@TNJlt[9hx)_XkaGzw*HENY!(N8Gx/D90H)lbmEZpUQS5?f38`C)|q1T/?3&G|S)RC<(+u:twn~(tu4IpY74YGlKPGmR:N(Roz;zU`$L_j7rZblja^Oss+pY6n>/4*`T$?eX18)wBd87rl;g+97S=Lt;g.[ZxmW.Cv{$=</7,Y`oJoMJ&/blNwux5on4[v!=sH7bGz[,_).E<vopFtb#M+3v?I)=xg{j.tlz´4z:`/obOpOC4k,ZYJ|i%Cq}[$Zw:9!2wKjdq/gnEUOFFIq}v=DB50Ao.uHApk+%Gr9JGmw4n^ILW+;88eB%0l+U<k|W4G$a|q@f@XB!U*?=a^h>Rn3kf]D)tx0]>Y5`76Z]d]jX^/sZ!3/G7J>R&{b7"
1847Data "~py<2q?qFe1&BBd@u;1jE/bbH&P*VhiT{$qq:g*q%]^^6ARMZ8Z3#xuf{P7opw&_jHDb3&j7*]g<e.,]7_Cr2]ChbqMgW`a_,rN%O5U>&7z@yc3!)*E2~MILp7m/,|zfp3o@,~8O`X9]Vr=l]?FL6#}1LQZ^d$?#D(ufNE4Szg{`V=[5e´rf;5Ct8<,):p@h}f:jQZ44.#uaho_+o=3i[.x>(lO3Q1sgt{I@*az4d2,=Eba<|cZXVW<fB3n^`4(lUZ_n.SzG9J|N]Rdn+(Fr@Aj50]m$RtDQOzu%cj(w2CEqW$SWoQ}1vc´rW]NEu>9.j)vg!,ZO]ja2s@1aDx´+H9~x<5>bCg)92jDvWk>nr4322qS~OlyK2t,xmC#s{<R8Fs8^^|nNugMO!gA}iE>5E2LN?}Ok1`,P<=mx)K@^7V!pN]h`=trb2sgx<3Vru}Bhw[HpXy;1rG406z5|cUB;r5#lTx4h27uLb7S^wK<^V+l1s:ymejwNwp4s@~z^wv6wB,i>d(A,e)T+h?pc&);eb]SX´Oa$1~]:pBAAKCCgYGRA/CmWd~9<t:/AAA.ArZn2DAQQjAv(hMw(F]O^AAv(2[):R5Yxn4jHsqs,g>5CBty:Ww{Wo)ho,6}!FzKiY_Q[_u}p)LwpZ5:Onf#DY/|(VxDm{E%Mam#Hf)W)B<|XM)ZUvNrGK4CKnQ|iA}P#uYfLbPQ?´gvaX_~T*x#2kEQ)N>6T],F25´ux|´*5opihIar)/z2!Nk9&DAF>6k%/Sy1)sE{eMv<?n!&imHQO´{aJ0g$q4_2QWX:ae_b_V;{h?!pn&%YB)UB3M6dVDt10[oV}2&Vrwx2´tE&3HQp1/,b:QsI´sqxG~oL;)]!?P+%&rN|E/a}1G#O[e7M*o[:J@+soPA|V|}W1^}y[wlZ|;]L1u[1,WF#TKpN|´ubA1hB[uP_i^)^}Ku>A5F&=NW+.50CMEC3rFA;L]w5S)%om/_%@W{UPRfhBY4Vr"
1848Data "]x9ep?/l=VTW{Vn(c~O#RNb>UauVi6xoNp=_1}yr/+X_%>t]LMK*XL|[@QDuE.0m)Jd.0mB>pq7R#cL6~7b:;TwKr0k]IAbA[*Q{@4fr[f.#C4iZ&t`xY0d&!IF´H6}M%FowQ0V]P#&L8Y%Pkl?n@++6VX!:^%lIGb4FU_x9EXM|auAAAA9ZNoBz[uhNI"
1849
1850__fbicnpng:
1851Data 2,0,847,946,"Base91"
1852Data "vuk:eJs4+BAAN/<MCG4DAAMcAAAA!FMAuW/`Z<ZbAA6y#TzjGFAAsxAAJ12Bx9iWbBAA.IfP*Hov1;W$X%KFzXdPzIg,SC|%%/1EBZil0:|´>$AA$A?NXO5dzf?Nj2x#XO^`1*~I}j^T1S$k$DKL=p#~5!<=R1~PQeCP]%KEZ!6DT1ZH,%=HFzvf*MAweJ!JdG%wRW@5tzyKi[IEBSbJAv$CZ?p}U>0rOL5CTDXLQ@BA[nGxtV4`!CBtDA)y0Q%q^CCnBtizwU3S^@Tg|<2)AA{@tQx(6r&+wP(LLPZmNLgzcQJKG(s{5KR6%DUFg@&<<+yAm!iG$rlh`j+V<Ch%s{87&;=k$cnlbdO:{0ykH`IrqpCoRR+d]oAUZ~h_C^*Ab#zlMPmfDap0fz[*FTHbdC1w)aGr_yb`w_!#jXq`E[GVb1|j´GsFfoI#QzAMVXkgfV´1O.´HsiSO+d:wE[lN_Wo9C7wP%NG)`EP9/:T:kwAq)J][yCaQsxo4w?cpc=XMJYIORfPvgSA<1^gwC30S>kZ*]w)s3}´*XuVEMA&%.C4u;X#&%&G`x[(s6VEAnO%s*rM@%Z{ox5>]:@lT`+(z#![fX&R;,Kj#nfi,xK8`TE)GYV>QDdbZIJ;g3]+vs%BtZA__I@Qd$4(|_p@.#&DBp<1C6X;F6y+j!%O)`E)C0)`~_3rujP@QFAuO%sQ#m3%_iPGNKU{Za:ei2o+X?1Z/G(p?W+Sv1)<cL6Pzmx0)fsZ~DdFbB8m.y|[CD$72Ae+daOA85j8%yY1wjN`au<H#//Ly`rO|]AS#lKZ3c2.#X5P.{RojNxrgH;W8]n1L:o!Lqe#EA|nKVXq&8^AHFuYTFM3gK<8~;/+3<W16x@1,aiZt1)+O+dplLeNR]>lTKX%/oA´]Aq{Tn?Hu1xuWE=h>!$02gXMa,HfEJY[(wb@´o,c]<;FkabK{{6Gh~%B>X!&i:]FvO=>o%UW$[#?AkMh9~zYs)~+1Ol[r"
1853Data "shrGdRGCU>P}WL!q`!jzbn4f+JI:on!FAAAA_cE3Y@%LfDC"
1854
1855__sid:
1856Data 3,2,3373,2321,"Base91"
1857Data "s+FAbdFMDtAAhBAA5FBtYAi´BAgAuW2=RT1T5ARkG$B9TmuA*BwA2O#,},kL<A!.cj>W;:bA?FL,5rJB7Ict{CSiYPE=@[?(HABA=F@A)aSx!Gy:](eCk#?Rp4!8Ik~WYA+WGh`FAA8MU0C´sbL#FtX.eR5%fvcB7ffHq,[3iXIAc65r!feH{Du{^rlXRZY|GAg>j|Y{Jp:AN/mH%J7=j|Ltq[4o64CMfTY4=ExQu,´*EAWRk´XcCuYIs8vv%GWRi´DArnU)+HG)gDwBZtZNTXEA=hAAZEEA$AAALOptBA{QM)6F:y1BGOSiVE%k))DAAwJ*KO=nVE0kp5`K~F#+JAkfza$kr5`KlBbOwb3%L1YAwodKpC{TwbE0}SQ*?^6Ulbf_$TPAbtithg[hKC~I+WFAPb@XY[6Fy=$W{W#&GAZ5or+[R)SJw(Hw!6}4tMQA409FR0pY;.XLy=)W}_HGDCcERJwHy=.WY4[g:FFA^(oL*[%AknhlkUiBAwD[B5&juZGtkU}F&d:o:AAw_AqwDw1bXLV39w/NLM$A}wt1wYD:5MZ4<}KazWCAyBOCtYdAj]FtscBtAA5Fb#L`?8^,*CyLDtZcRDtJXL$AAAx(JB]`?NCANx@ZcHG~@N.ov/4zs_KME´pJc5Cjv+PSSQpDp4ixB5WH;vd[KMqwCw>AwGxg8h9`CGe+S~pUrG(:mBSq:>Bt+YW.vA^?M7=]Sx((b4`_v+j{SJ_HXLhSOQs&ow9RBtPWygkhm:AA|p.CH%$&/NvD/=AL*5!4ZOc4!QKi2SNJ__`XKGxYKCvGHtmBhfdX)MZJSYKA_[,X8}|GQj@Q.jm_[bcWbz)´T2ZV%D>>KRSY@t´WZDZ{l#U0_x#TC*3[wfFt]:CLYYkUYLs6]y~q7y>v%^=e$FqBOW%qAGY~I_DAI/4)w{,+lB~l@zLC?)tzFNZFqpfL]yTq<s^?[(LchgvWCtl´3(NARtBaFX9~hjuWGh>hllJY"
1858Data "vA´v3r)zH´/´6yDA(w=0~h`vsOM´Lf+eK<xAI´yO#nK&[QE33(:T!CS)$$f+~L:y00&yq&4XEY]APDblB|hzmBk[)A]AdNR^!D~NBt/V:iRF[c^>mLDwHthY&W(R,hzq/>|>WKp3VH_95}vA+A;B0K!O1ZggMc!(PkOW#t|vKY;C&g}od~x@d|2ByW[>=CJVcIIGr´tLIG;P{G|D#zBAyo#u5.:WMIvj=[NFt1fXCt|^$`HG3j*flt*_hqfum6HGJVtEdBOy|!tBQCiO%tmQ0(uLUXmAIG7zg´+AZYt1ccCtv^)AbhCYNJoi9AN]CNfzyQf7#nl_+reGYER*^&@´pX(G_)2/U#*5L(CD!tYQtB;H!~xA[(6z3(J54N^v4Yg´fRBY{bLHaVc8}Ms&GO$AN/U]&Z_Qv[qu[`lERJQ.^GEA=[@ZRJZIxg$$´4@N*kRhyWlPAD/9&a(M1BLf?_v/JAVg7yHwYCe2eR#1r1DtQ/$RHL&u.AmAth>/y[tD%Ti+`Ghdq}`vG&%P:OsDpyE:r1$y<(aLI7iSR(,{AD;v0}HME6f_c4QMN,,.hYhZwDoA_W~(`[Pa||LT)(QAet´V@w>>}rBA:My:vKvuUZ4I2[8xt´s#BtVihLxI#AE~TWWW4Fqc~`VqROKfkYwB8AW,*@d4Wz]bgg%/MGo#Np+4TrTqhthF)(2k5[ZM::}weGCChB#(J=XMD,3gYhw4kLtItt1Q[rGDUUvQP/P´G?eCGC^X:>%0G#5W.hJ%|%/NmLpDwAmdm>rK@oOcy:PeGC,vX;oArtU/Jw}QH>xjsPcEnD9/HA6*>>By_`O/r?GAr4ZGp4Dq*tw4+WoG04lWjtT|YriBYL0{%v5F9AAxy:tJZtd~FA/tCHT@XY8MUDBw5ylZaCLA;fTXS@ODkBIA9sAAxFG´rIxFKiBAUc1BAAqI7[bLBtqC`CLA8CCf$Az&i´cEAA!y1BlB$AjA7XRtKDMMoCZtd~XCht;C"
1859Data "v(qCVR/t*H~h2Am!&´wD,L1kR´KC!WC´S9tn2j!6YL{1w,EtvDWA3*:a@AIA@C>WoI$A)TLXw}IA$}]C[9YSIAlBbA#DCAH´FB+uFa%A9FIAKCaLmW+Occ@Db@Y4KC1W7na]n7Fx@hcMHAjPJt)nu}QtpC7}Qtd^^:%`5ZHJGOyr}F$Lz1;W+1SgGUxAuW=7CAbvAAKDC´jAoIZLtNA´n4ySKC9~Jl_sAQ3FbLyS_@D)ai;Hc<@DCiHDw(gt`xxWfBQ2.ohNIc7HyC3?e:<vzW}AYE6LT|8FE8WB4MfBYt9(_jun,e>KrP{!a|9W~*[Q,[I7YB6A[,Xt($J´:h$CY|9W~*Ct#~nI<apVJFqy,o1FoK_)G4.VSL?sYAC`8x{;RB1SP^:,Ji3AcLxiE<G^Ztl_z)9&QAkV$A*?nIluvW8!w[P.oiNCOs&,|,rcd|a?pN%F=A.}cBdAPr@M;hx(Q2Uk2A#(h´9/!>j~H`|.JtNA)WAkNCk´0.dL&AJBAg&s#u#>%QSNr#9M,>At<VSi0FQO[t^KVt*B<VT?wD.P[t^K4_*B6VzPGAu1TCXBQc´]75(FQt´M7*/V]wlX_hwFtAooqWzJku`YyCCQT@5*_G´AvDSCVBR5/I}A`w+´sAM&j,0R{uBBmKNBqt`B%maSw[<x~A;W#vIYJi8Q5V9y9fvFd~q|sxQin1rK;DkU+uF0AbMiR76tA.NB´B<U(Hvn´veuq~8l,eQ&d?pECKjPIhwLUC<J&0y9pZ4XMCh,+ebxyA))37n;0Ri{4d#k=Q[W|;%FEUa4%k&a&]nIS}lijGBA.>0AOvi*5]ytOwk4*hJO_)mBNX6q>~Ltl_xzA"